在这个回合制游戏中使用 Reader monad 是否正确?

Is it correct to use the Reader monad in this turn-based game?

我需要学习使用 Reader monad。 (还有作家和国家)。

我进行的游戏竞赛始终包含在整个游戏中有效的全局参数。还有一堆只在一个回合内有效的参数。

我用很多函数结束了所有最新的比赛,几乎所有的函数都有 Game 和 Turn 作为输入参数。

在阅读了 reader monad 之后,我正在考虑拥有:

data Game = Game AllNeeded StrategicPositions AndGameRelatedStuffs
data Turn = Turn PlayersPositions AndTurnDependentStuffs 

并且对于每个循环,当我收到与回合相关的数据时,我计划有一个变量 Reader Game Turn:

turnReader = Reader currentGame currentTurn
let actionToPerform = play turnReader

您认为这是 Reader monad 应用的好例子吗? 你认为我 can/should 蒙着眼睛学习在这种情况下使用 Reader monad 吗?或者是否有更合适的 monad,比如 State?

Reader monad 当你有一个 immutable state 你想在你的计算中读取时使用。基本上就像将一个额外的参数隐式传递给所有单子操作。

似乎在您的游戏中您确实想要改变 某些东西(即游戏的回合或状态)。在这种情况下,State monad 可能更容易使用。

为了使用 Reader 你必须将所有依赖于状态的动作分组,在 monad 中执行它们然后 monad 之外改变状态和 运行 修改状态等的新单子计算。这听起来很麻烦。

请注意,使用 Reader 实际上与使用 State 类似。简单地说:不允许 put 操作(和派生)。所以你可以使用 Reader 开始写作,如果你遇到一个你想修改状态的地方,你知道使用 State 可能会更好。 或者反之亦然:从使用 State 开始,如果您最终从未修改状态,请将其替换为 Reader.

假设 Turn 值每回合都在变化,而 Game 没有,StateT Turn (ReaderT Game IO) 似乎是合理的。为此,您需要阅读 monad 转换器(我个人喜欢 "Monad Transformers Step by Step" (PDF))。