作家Monad是否与State Monad有效?

jor*_*an3 19 monads scala state-monad scalaz writer-monad

有一个伟大的教程在这里,这似乎暗示,我认为作家单子基本上是做代表的工作的特殊情况,元组对象(A,B).作者在左边积累了值(即A),并且A与它有相应的Monoid(因此它可以累积或改变状态).如果A是一个集合,那么它就会累积.

State Monad也是一个处理内部元组的对象.它们都可以是flatMap'd,map'd等等.这些操作对我来说都是一样的.他们有什么不同?(请用scala示例回复,我不熟悉Haskel).谢谢!

Tra*_*own 36

你对这两个单子密切相关的直觉是完全正确的.区别在于它Writer更加有限,因为它不允许您读取累积状态(直到您在结束时兑现).你可以用a状态做的唯一事情Writer就是把更多的东西放到最后.

更简洁,State[S, A]是一种包装S => (S, A),同时Writer[W, A]是一个包装(W, A).

考虑以下用法Writer:

import scalaz._, Scalaz._

def addW(x: Int, y: Int): Writer[List[String], Int] =
  Writer(List(s"$x + $y"), x + y)

val w = for {
  a <- addW(1, 2)
  b <- addW(3, 4)
  c <- addW(a, b)
} yield c
Run Code Online (Sandbox Code Playgroud)

现在我们可以运行计算了:

scala> val (log, res) = w.run
log: List[String] = List(1 + 2, 3 + 4, 3 + 7)
res: Int = 10
Run Code Online (Sandbox Code Playgroud)

我们可以做同样的事情State:

def addS(x: Int, y: Int) =
  State((log: List[String]) => (log |+| List(s"$x + $y"), x + y))

val s = for {
  a <- addS(1, 2)
  b <- addS(3, 4)
  c <- addS(a, b)
} yield c
Run Code Online (Sandbox Code Playgroud)

然后:

scala> val (log, res) = s.run(Nil)
log: List[String] = List(1 + 2, 3 + 4, 3 + 7)
res: Int = 10
Run Code Online (Sandbox Code Playgroud)

但这有点冗长,我们也可以做很多其他事情State,我们无法做到Writer.

因此,故事的寓意是你应该Writer随时使用- 你的解决方案将更清洁,更简洁,并且你会对使用适当的抽象感到满意.

但是,通常Writer不会给你所需的所有力量,并且在那些情况下State会等你.