如何堆叠 State 和 IO monad

How to stack the State and IO monads

在 Connect4 游戏中:

我的想法是:

这个想法对吗?

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

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

我可以这样堆叠这些monads(State,IO)吗?

我认为您应该只编写一个工作程序,然后 generalize/refactor 它而不是预先过度设计。 您需要 State[S, A] 用于业务逻辑,IO[A] 用于与控制台交互。但你不必混合它。

然后在主要 class 中编写 user-interaction 循环,您可以利用 StateT 统一两种类型。

顺便说一句 IO[State[S,A]] 看起来不是很有用的类型。它说你可以从现实世界中读取 State[S, A]State 是一个函数。没有明智的方法可以从现实世界中读取函数。所以很可能你需要一些不那么强大的东西。当然,这种类型在 monad 转换器的上下文中是有意义的。

cats 中的

State 实际上被定义为 monad transformer 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 cats 文档的 interleaving effects 部分找到更多关于使用效果 monad 和 StateT 堆叠状态 monad 的信息。