5

我正在尝试在我的电梯项目中开始使用 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)
  }

所以,这应该以某种方式使用状态单子重写。但我就是不明白,如何。试试这个:

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中状态单子的任何好的教程/解释,展示如何使用getsput等?

4

2 回答 2

2

警告:我从未使用过 Scala 状态单子。但是,我想我看到了它像你说的那样表现的原因。

onSubmit看到旧的pass,不是那个,我在put

好吧,看看你在做什么:

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

首先,我不认为你正在投入你认为你正在投入的东西。试试这个:

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

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

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

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

另外(尽管我不知道SHtml或做什么&)我非常怀疑这是否真的有效。很难解释我为什么这么认为,但SHtml正如 Debilski 评论的那样,这可能与在其内部构建状态表达式不友好有关。SHtml.password似乎期望你给它一个任意的副作用功能;这种设计选择立即使其对您尝试做的事情的功能方法不友好。

于 2011-12-13T23:55:48.607 回答
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

在 word count 示例中,它计算 3 个值,并且 wordcount 值是通过使用 state 计算的。我希望这有帮助。

于 2011-12-13T14:15:55.943 回答