Haskell退出状态monad早期(警卫?)

Sea*_*ess 3 monads haskell monad-transformers

我有一个表示我的应用程序的游戏状态的类型,因为这个问题假装它是一个简单的东西:

Game { points :: Int }
Run Code Online (Sandbox Code Playgroud)

我使用State monad定义我的游戏逻辑.

type GameState a = StateT Game a

addPoints :: Int -> GameState ()
addPoints num = do
    Game p <- get
    put $ Game (p+num)
Run Code Online (Sandbox Code Playgroud)

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

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)
Run Code Online (Sandbox Code Playgroud)

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

addPoints num = do
    guard evenResult
    ...

-- or this
addPoints num = do
    guardIsEvenResult
    ...
Run Code Online (Sandbox Code Playgroud)

如果它击中了守卫,我希望它独自离开状态,并且在阻挡中不做任何其他事情.

我该怎么做?MonadPlus 似乎接近可能,但我不确定我是否可以使用mzero来说"返回你所拥有的状态".谢谢!

ehi*_*ird 6

导入Control.Monad.Trans.Maybe和使用MaybeT在上面StateT.然后,你可以使用mzero中止计算,还是像凯文·巴拉德说,guard condition要停止,如果conditionFalse; 你所要做的就是把每个街区都包括在里面runMaybeT.(请注意,您要么必须liftStateTmonad 上定义每个选项,要么更改其类型以使用具有所需状态的任何monad,例如operation :: (MonadState m Game) => ....)

请注意,即使您没有直接使用它,也可能包含其中的transformersControl.Monad.Trans.Maybe; mtl包含标准monad模块的包Control.Monad.State依赖于它.