试图了解scalaz state monad

时间:2011-12-13 12:49:40

标签: scala lift scalaz state-monad

我正试图在我的电梯项目中开始使用scalaz。为此,我正在重写一些代码来满足风格。考虑用于登录用户的代码:

  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:根据答案更新了示例。

有关scalaz状态monad的任何好的教程/解释,展示如何使用getsput等?

2 个答案:

答案 0 :(得分: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个值,并且通过使用状态计算wordcount值。我希望这会有所帮助。

答案 1 :(得分:2)

警告:我从未使用过Scala状态monad。但是,我认为我看到它的行为就像你说的那样。

  

onSubmit看到旧的pass,而不是那个,我是put'ting

好吧,看看你在做什么:

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

首先,我认为你没有按照自己的想法投入。试试这个:

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

其次,我认为你没有得到你认为你得到的东西。我不知道Scalaz状态monad是如何工作的,但它应该是这样的东西

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

我认为您不会使用pass来指代变化的状态; pass只是开始时给状态计算的值,这可以解释User.logIn("username", pass)使用“旧”oassword的原因。

另外(虽然我不知道SHtml&做什么)但我非常怀疑这实际上会有效。很难解释为什么我这么想,但它与SHtml有关,可能与内部构造状态表达式不友好,正如Debilski评论的那样。 SHtml.password似乎期待你赋予它一个任意副作用的功能;这种设计选择立即使得它对你试图做的事情的功能性方法不友好。