2011-12-13 51 views
5

我想在我的電梯項目中開始使用斯卡拉茲。爲此,我重寫了一些代碼以符合風格。考慮登錄用戶的代碼:試圖瞭解斯卡拉茲狀態monad

def login: CssSel = { 
    var password = "" 
    def submit() { 
     if (doLogin) S.redirectTo("/index") 
     else S.error("Wrong password") 
    } 
    "name=pwd" #> SHtml.password(password, password = _) & 
    "type=submit" #> SHtml.onSubmitUnit(submit) 
    } 

因此,這應該用某種狀態monad改寫。但我不明白,如何。 嘗試這樣的:

val result = for { 
    s  <- init[String] 
    pass <- SHtml.password(s, put(_)) 
    newPass <- init[String] 
    res  <- "name=pwd" #> pass & 
       "type=submit" #> SHtml.onSubmit { _ => 
       if (User.logIn("username", newPass)) S.redirectTo("/index") 
       else S.error("Wrong password") 
       } 
} yield (newPass, res) 
result ! "" 

UPD:更新例如,根據答案。

斯卡拉的狀態monads的任何好的教程/解釋,展示如何使用getsput等?

+0

你看過我早期的問題/答案嗎? http://stackoverflow.com/questions/7734756/scalaz-state-monad-examples – huynhjl

+2

我不確定這是否真的很實用。你不能只使用一些狀態monad,並且魔法地去掉你的代碼中的所有'var's。爲了這個工作,你必須有一些方法來鏈接Lift的'SHtml'回調方法不支持的狀態變化。 (我認爲Lift的整個概念正是你使用隱藏在許多閉包中的變量)。然而,我很樂意被證明是錯誤的,並且看到了一個這樣的例子。 – Debilski

+0

你說得對。謝謝。 – folone

回答

2

警告:我從來沒有使用Scala狀態monad。不過,我想我會看到它所表現的原因,就像你說的那樣。

onSubmit看到老pass,而不是一個,我put「婷

好吧,看在你在做什麼:

... { pass => 
    ... SHtml.password(pass, _ => put(pass)) 
    ... User.logIn("username", pass) 
} 

首先,我不知道認爲你正在把你認爲的東西放進去。試試這個:

... SHTML.password(pass, newPass => put(newPass)) 

其次,我不認爲你得到你認爲你得到。我不知道Scalaz狀態單子是如何工作的,但它應該是東西這樣的:

... User.logIn("username", get()) 

我不認爲你用pass指的變化狀態; pass只是給予狀態計算開始的值,這可以解釋爲什麼User.logIn("username", pass)正在使用「舊」密碼。

此外(雖然我不知道SHtml或什麼&做)我非常懷疑這將實際上工作。 Debilski評論說,很難解釋我爲什麼這麼想,但它與SHtml有關,可能不友善於在其內部構建狀態表達式。 SHtml.password似乎預計你給它一個任意的副作用函數;這種設計選擇立即使它對你正試圖做的事情的功能性方法不友好。

+1

這是一個不完整的可能很糟糕的答案。那些真正瞭解Lift和Scalaz的人:請適當地投票/評論以確認/否定我的結論。 –

2

我發現,最好的例子scalaz到目前爲止有這些: http://etorreborre.blogspot.com/2011/06/essence-of-iterator-pattern.html?m=1 http://etorreborre.blogspot.com/2011/12/pragmatic-io.html?m=1 和後續窗口。 從scalaz的例子本例:) https://github.com/scalaz/scalaz/blob/scalaz-seven/example/src/main/scala/scalaz/example/WordCount.scala

在單詞計數示例它計數3個值和單詞計數值通過使用狀態計算。我希望這有幫助。