州Monads:交换另一种模式?

J C*_*per 4 monads haskell abstraction boilerplate state-monad

所以我正在Haskell中编写一个游戏,我将玩家视为一系列与各种转弯阶段相关的状态改变函数.最初,这看起来像:

let game'  = phase1 game
    game'' = phase2 game'
-- etc.
Run Code Online (Sandbox Code Playgroud)

国家monadosity的主要候选人,对吧?这导致更优雅:

do
  phase1
  phase2
-- etc.
Run Code Online (Sandbox Code Playgroud)

然而,似乎我必须改变phase1,phase2等等以一个样板"状态获取"步骤开始:

phase1 = get >>= \game -> -- ...
Run Code Online (Sandbox Code Playgroud)

我希望有一种方法可以抽象出来,所以我可以避免调用者和被调用者都使用样板文件.我太新了,不知道这是什么方式(这是我的第一个真正的Haskell项目).有什么建议?

luq*_*qui 8

嗯,它还不是很符合monadosic.这是Endo幺半群的主要候选人.这导致更优雅

game = mconcat [ phase1, phase2, ... ]
Run Code Online (Sandbox Code Playgroud)

每个阶段都写成:

phase1 = Endo $ \game -> ...
Run Code Online (Sandbox Code Playgroud)

如果您需要在每个阶段中返回一些额外数据以及新状态,您将转移到monad.在这种情况下,一个简单的函数将使您的样板更容易忍受:

phase :: (GameState -> GameMonad a) -> GameMonad a
phase f = f =<< get
Run Code Online (Sandbox Code Playgroud)

然后编写一个阶段:

phase1 = phase $ \game -> do ...
Run Code Online (Sandbox Code Playgroud)

但是如果你想使用状态,你可能不得不给它一个名字(除非你可以通过使用获取数据访问器来确定点自由度),在这种情况下你不能得到比一个函数和一个lambda.