我试图理解并对State Monad感到满意,所以我基本上都是通过复制一个预先存在的例子。 '州'只有一扇门在关闭时推开,在拉开时关闭,如果它打开的话。如果它在打开时推动或在关闭时拉动,它什么都不做。所以下面的代码似乎按预期工作。
def main(args: Array[String]): Unit = {
import Monad._
// Push to open, pull to close
case class Door(open: Boolean = false)
trait Action
case object Push extends Action
case object Pull extends Action
def update: Action => Door => Door = action => door => {
val curr = (action, door)
println(curr)
curr match {
case (Push, Door(op)) => if (op) door else Door(!op)
case (Pull, Door(op)) => if (op) Door(!op) else door
}
}
val sm = stateMonad[Door] // Code for 'stateMonad' not shown
def simulate(inputs: List[Action]) = for {
_ <- sm.sequence(inputs map (a => State.modify(update(a))))
s <- State.get
} yield ()
val actions = List(Push, Pull, Pull, Push)
val r = simulate(actions).run(Door())
println(r) }
//上面的代码导致:
(Push,Door(false))
(Pull,Door(true))
(Pull,Door(false))
(Push,Door(false))
((),Door(true))
但是,如果我将第一个case语句更改为:
case (Push, Door(op)) => if (op) door else Door(false)
我认为这将是同样的事情...... //结果是:
(Push,Door(false))
(Pull,Door(false))
(Pull,Door(false))
(Push,Door(false))
((),Door(false))
这对我来说真的很棒,但是我找不到,否则我就无法解释发生了什么。有人可以帮忙吗?
感谢。
答案 0 :(得分:1)
与评论中提到的Artsiom一样,您混合了Push
/ Pull
和Door(true)
/ Door(false)
。
如果门是打开的话,模式匹配可能更容易:
curr match {
case (Push, Door(false)) => Door(true)
case (Pull, Door(true)) => Door(false)
case _ => door
}
更明确的是将一些方法添加到Door
:
case class Door(isOpen: Boolean = false) {
def isClosed = !isOpen
def open = copy(isOpen = true)
def close = copy(isOpen = false)
}
然后,模式匹配可能如下所示:
action match {
case Push if door.isClosed => door.open
case Pull if door.isOpen => door.close
case _ => door
}
使用scalaz State
检查:
import scalaz._, Scalaz._
def updateDoor(action: Action): State[Door, (Action, Door)] =
State(door => action match {
case Push if door.isClosed => (door.open, (action, door))
case Pull if door.isOpen => (door.close, (action, door))
case _ => (door, (action, door))
})
val actions = List(Push, Pull, Pull, Push)
val (end, steps) = actions.traverseU(updateDoor).run(Door())
这给你的第一个例子提供了类似的输出:
scala> steps.foreach(println)
(Push,Door(false))
(Pull,Door(true))
(Pull,Door(false))
(Push,Door(false))
scala> println(end)
Door(true)