有一个很棒的教程here这似乎向我表明 Writer Monad 基本上是一个特殊情况的元组对象,它代表 (A,B) 执行操作。 writer 在左侧累积值(即 A),并且 A 具有相应的 Monoid(因此它可以累积或改变状态)。如果 A 是一个集合,那么它会累积。
State Monad 也是一个处理内部元组的对象。它们都可以是 flatMap'd、map'd 等。操作对我来说似乎是一样的。它们有何不同? (请回复一个 scala 示例,我不熟悉 Haskel)。谢谢!
最佳答案
您认为这两个单子(monad)密切相关的直觉是完全正确的。区别在于 Writer
受到更多限制,因为它不允许您读取累积状态(直到您最后兑现)。您唯一可以对 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
现在我们可以运行计算:
scala> val (log, res) = w.run
log: List[String] = List(1 + 2, 3 + 4, 3 + 7)
res: Int = 10
我们可以用
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
进而:
scala> val (log, res) = s.run(Nil)
log: List[String] = List(1 + 2, 3 + 4, 3 + 7)
res: Int = 10
但这有点冗长,我们还可以用
State
做很多其他事情我们无法使用 Writer
.所以这个故事的寓意是你应该使用
Writer
只要有可能,您的解决方案就会更干净、更简洁,并且您会因为使用了适当的抽象而感到满意。经常
Writer
但是,不会为您提供所需的全部功能,在这些情况下 State
会等你的。
关于scala - 作家单子(monad)实际上与状态单子(monad)相同吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23942890/