2015-10-20 56 views
0

我想了解,並與國家Monad舒適,所以我基本上是通過複製一個先前存在的例子。 '國家'只是一扇門,如果它在關閉時被推開,當被打開時被關閉時會關閉。如果在關閉時打開或拉出時,它不起作用。所以下面的代碼似乎按預期工作。分心雖然試圖瞭解國家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)) 

這對我來說確實是一個非常愚蠢的事情,但我找不到,我也沒有解釋發生了什麼。有人可以幫忙嗎?

謝謝。

+1

你居然混了推送的意義,在你的代碼拉。評論說''推開,拉關'。好的,你從默認關閉的門開始,在第一次迭代之後應該打開門(「推開」)。 –

回答

1

像Artsiom在評論中提到的,你正在混合Push/PullDoor(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 
} 

檢查斯卡拉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) 
+0

對不起,夥計們爲了頭腦發mistake的錯誤。累了,我想 –

+0

感謝真棒博覽會和scalaz的例子!很有幫助。 –