Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/webpack/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 哈斯克尔提早退出州政府(守卫?)_Haskell_Monads_Monad Transformers_Alternative Functor - Fatal编程技术网

Haskell 哈斯克尔提早退出州政府(守卫?)

Haskell 哈斯克尔提早退出州政府(守卫?),haskell,monads,monad-transformers,alternative-functor,Haskell,Monads,Monad Transformers,Alternative Functor,我有一个代表我的应用程序的游戏状态的类型,对于这个问题,假设它很简单,如: Game { points :: Int } 我用状态单子定义游戏逻辑 type GameState a = StateT Game a addPoints :: Int -> GameState () addPoints num = do Game p <- get put $ Game (p+num) 如果它击中了防护装置,我希望它离开状态,而不在块中执行任何其他操作 我怎么做?对于

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

Game { points :: Int }
我用状态单子定义游戏逻辑

type GameState a = StateT Game a

addPoints :: Int -> GameState ()
addPoints num = do
    Game p <- get
    put $ Game (p+num)
如果它击中了防护装置,我希望它离开状态,而不在块中执行任何其他操作


我怎么做?对于MonadPlus来说,这似乎几乎是可能的,但我不确定是否可以使用mzero来表示“返回您在您的状态中已经拥有的内容”。谢谢

导入
Control.Monad.Trans.Maybe
并在
StateT
上使用。然后,您可以使用中止计算,或者如Kevin Ballard所说,
条件
如果
条件
,则停止计算;您所要做的就是将每个块括在
runMaybeT
中。(请注意,您必须
提升
StateT
monad上定义的每个选项,或者更改它们的类型以使用任何具有所需状态的monad,如
操作::(MonadState m Game)=>…

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

我想我是在充实猪倌对这个问题的评论

ensure :: GameState Bool -> GameState () -> GameState ()
ensure p k = do 
  t <- p 
  when t k

addPoints num = do
  ensure (evenResult num) $ do
  ...
sure::GameState Bool->GameState()->GameState()
确保pk=do

t
StateT
已经是一个
MonadPlus
。你试过仅仅使用
Control.Monad.guard
吗?@KevinBallard:
StateT s m
如果
m
是,那么它只是一个
MonadPlus
;实例只是将
mzero
mplus
提升一级。Control.Monad.when是你的人?诚然,当
需要一个
Bool
值时,
是一个麻烦,而不是一个计算出
Bool
。但罗马不是一天烧成的。如果您的
test
位于
m Bool
,您可以编写
(test>=)。当$action
时进行翻转,这是一个相当复杂的问题。或者,我可以将sure写成
sure::(Game->Bool)->GameState()->GameState()
,我的所有谓词函数都写成
where::Game->Bool
,而不是
where::GameState Bool
addPoints num = do
    guard evenResult
    ...

-- or this
addPoints num = do
    guardIsEvenResult
    ...
ensure :: GameState Bool -> GameState () -> GameState ()
ensure p k = do 
  t <- p 
  when t k

addPoints num = do
  ensure (evenResult num) $ do
  ...