Scala 如何堆叠状态和IO单子

Scala 如何堆叠状态和IO单子,scala,functional-programming,monads,scala-cats,Scala,Functional Programming,Monads,Scala Cats,在Connect4游戏中: 我们从一个空网格开始 两名玩家将棋子x和o放置在网格上 第一个在一条线上完成4个棋子的玩家获胜 这是一个基于文本的控制台游戏 我的想法是: 在游戏的每一步,网格都在从一个状态过渡到另一个状态 因此我需要使用状态单子 因为这是一个基于控制台的应用程序,涉及io 在这种情况下,我还需要使用IO monad 这种想法正确吗 假设以上是正确的,以下哪一项是正确的 输入StateInIO[S,A]=IO[State[S,A]] 类型IOInState[S,A]=状态[

在Connect4游戏中:

  • 我们从一个空网格开始
  • 两名玩家将棋子x和o放置在网格上
  • 第一个在一条线上完成4个棋子的玩家获胜
  • 这是一个基于文本的控制台游戏
我的想法是:

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

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

  • 输入StateInIO[S,A]=IO[State[S,A]]
  • 类型IOInState[S,A]=状态[S,IO[A]]
我赞成第二种选择,这对我来说更有意义


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

我认为您应该编写一个工作程序,然后对其进行概括/重构,而不是预先设计过度。 业务逻辑需要
状态[S,A]
,与控制台交互需要
IO[A]
。但你不必把它混在一起

然后在编写用户交互循环的主类中,可以利用将两种类型统一起来的
StateT


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

状态
在CAT中实际上被定义为monad transformer的类型别名
StateT[F[\u],S,A]
,其中
F[\u]
是效果类型。此别名用
Eval
修复了
F[\u]
,因此它看起来像
类型State[S,A]=StateT[Eval,S,A]
。在您的情况下,您应该定义自己的IO状态,比如
类型IOState[S,A]=StateT[IO,S,A]

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


您可以在cats的状态文档部分中找到更多关于将状态单子与
StateT
叠加的有效单子的信息。

对于
F=IO
IO[S=>IO[(S,A)]
,而
IO[state[S,A]
本质上是
IO[S=>(S,A)]
,因此,中间一段似乎不太正确。@Andreytukin对,我改了。谢谢。另一方面:声明“此数据类型表示形式为
S=>F[(S,A)]
的计算”,无论出于何种原因,外部
F
被省略了。。。我不知道为什么。