如何堆叠 State 和 IO monad

jak*_*ack 4 monads functional-programming scala scala-cats

在 Connect4 游戏中:

  • 我们从一个空的网格开始
  • 两名玩家将 x 和 o 放在网格上
  • 第一个达到 4 个棋子的玩家获胜!
  • 这是一个基于文本的控制台游戏

我的想法是:

  • 在游戏的每一步,网格都从一种状态过渡到另一种状态
  • 因此我需要使用 State monad
  • 并且因为这是一个基于控制台的应用程序,涉及 io
  • 在这种情况下,我还需要使用 IO monad

这种想法正确吗?

假设以上是正确的,以下哪一项是正确的?

  • 类型 StateInIO[S,A] = IO[State[S,A]]
  • 类型 IOInState[S,A] = 状态 [S,IO[A]]

我赞成第二种选择,对我来说更有意义。

我可以用这种方式堆叠这些 monads (State, IO) 吗?

Krz*_*sik 5

State在猫中实际上被定义为 monad 转换器的类型别名,StateT[F[_], S, A]其中F[_]是效果类型。这个别名的修复F[_]Eval,所以它看起来像type State[S, A] = StateT[Eval, S, A]。在您的情况下,您应该定义自己的 IO 状态,例如type IOState[S, A] = StateT[IO, S, A].

StateT[IO, S, A]对应IO[S => IO[(S, A)]],我觉得它是更有用的堆栈,因为您现在可以轻松地将使用此堆栈的代码与使用 IO 的应用程序的其余部分连接起来。

你可以在 State from cat 的文档中找到更多关于 stacking state monad with effect monad with StateTin section interleaving effects的信息。