Haskell 国家单子:用一种模式换另一种模式?

Haskell 国家单子:用一种模式换另一种模式?,haskell,abstraction,monads,boilerplate,state-monad,Haskell,Abstraction,Monads,Boilerplate,State Monad,所以我用Haskell写了一个游戏,我把一个玩家的回合表示为一系列与不同回合阶段相关的状态改变函数。最初,这看起来像: let game' = phase1 game game'' = phase2 game' -- etc. 州一级放射治疗的主要候选人,对吗?这将导致更优雅的: do phase1 phase2 -- etc. 然而,似乎我必须改变phase1,phase2,等等,从样板文件“状态获取”步骤开始: 我希望有一种方法可以把这一点抽象出来,这样我就可以避免打电

所以我用Haskell写了一个游戏,我把一个玩家的回合表示为一系列与不同回合阶段相关的状态改变函数。最初,这看起来像:

let game'  = phase1 game
    game'' = phase2 game'
-- etc.
州一级放射治疗的主要候选人,对吗?这将导致更优雅的:

do
  phase1
  phase2
-- etc.
然而,似乎我必须改变
phase1
phase2
,等等,从样板文件“状态获取”步骤开始:


我希望有一种方法可以把这一点抽象出来,这样我就可以避免打电话的人和被叫人都使用样板文件。我只是太新了,不知道这种方式是什么(这是我第一个真正的Haskell项目)。有什么建议吗?

嗯,它还不完全是单体的。这是幺半群的主要候选者。这将导致更优雅的设计

game = mconcat [ phase1, phase2, ... ]
每个阶段都写着:

phase1 = Endo $ \game -> ...
phase1 = phase $ \game -> do ...
如果需要在每个阶段中返回一些附加数据以及新状态,则可以移动到monad。在这种情况下,一个简单的函数将使您的样板更容易接受:

phase :: (GameState -> GameMonad a) -> GameMonad a
phase f = f =<< get

但是如果你想使用状态,你可能必须给它一个名字(除非你可以通过,比如说,使用or来欺骗无点性),在这种情况下,你不能得到比函数和lambda更简洁的名称。

。第三阶段。第二阶段。第1阶段$game
?或
game=mconcat$map Endo[phase1,phase2,…]
phase1游戏=…
附录。麦康卡特。map Endo=foldr(.)id
我建议使用
Endo
更多地作为一种抽象,而不仅仅是一种组合函数列表的技术。我不知道我说的是什么意思
phase1 = phase $ \game -> do ...