Haskell 提前退出状态 monad(守卫?)

标签 haskell monads monad-transformers alternative-functor

我有一个类型代表我的应用程序的游戏状态,对于这个问题假装它很简单,例如:

Game { points :: Int }

我用 State monad 定义我的游戏逻辑。

type GameState a = StateT Game a

addPoints :: Int -> GameState ()
addPoints num = do
    Game p <- get
    put $ Game (p+num)

我希望能够简单地丢弃一些输入

evenResult num = do
    Game p <- get
    return $ even (p + num) 

addPoints num = do
    isEven <- evenResult num
    if isEven then return () else do
    Game n <- get
    put $ Game (n+num)

我想要一个看起来像这样的语法

addPoints num = do
    guard evenResult
    ...

-- or this
addPoints num = do
    guardIsEvenResult
    ...

如果它击中了守卫,我希望它不去管这个状态,并且在 block 中什么都不做

我该怎么做?使用 MonadPlus 似乎接近可能,但我不确定我是否可以使用 mzero 说“返回你在你的状态下已经拥有的东西”。谢谢!

最佳答案

进口Control.Monad.Trans.Maybe并使用 MaybeT StateT 之上.然后,您可以使用 mzero 中止计算,或者像 Kevin Ballard 所说的那样,<a href="http://hackage.haskell.org/packages/archive/base/latest/doc/html/Control-Monad.html#v:guard" rel="noreferrer noopener nofollow">guard</a> condition如果 condition 停止是False ;您所要做的就是将每个 block 包含在 runMaybeT 中. (请注意,您要么必须 lift 您在 StateT monad 上定义的每个选项,要么更改它们的类型以使用具有您所需状态的任何 monad,例如 operation :: (MonadState m Game) => ... 。)

请注意,您可能拥有 transformers包装Control.Monad.Trans.Maybe包含在,即使你没有直接使用它; mtl包,其中包含标准的 monad 模块,如 Control.Monad.State , 取决于它。

关于Haskell 提前退出状态 monad(守卫?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10289486/

相关文章:

javascript - 用于 API 响应的 Monad

haskell - 在 IO 之上构建 monad 转换器堆栈是否有正当理由?

haskell - 为什么 ListT monad 转换器被认为是错误的 - 它违反了哪些 monad 法则?

haskell - 我可以从程序中更改堆栈大小限制吗?

haskell - 如何将多态函数应用于动态值

regex - "=~"提高 "No instance for (RegexContext Regex [Char] [String])"

haskell - 在 haskell 的类型类中专门化一种方法?

haskell - 您如何识别一元设计模式?

haskell - 我应该使用 monad 还是 EfforT monad 转换器?

haskell - 为所有 MonadTrans 实例提供类型类实例