尝试理解 scalaz 状态 monad

发布于 2024-12-20 23:58:06 字数 973 浏览 5 评论 0原文

我正在尝试在我的电梯项目中开始使用 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 中状态单子的任何好的教程/解释,展示如何使用 getsput 等?

I'm trying to start using scalaz in my lift project. For that purpose I'm rewriting some code to meet the style. Consider a code for logging in a user:

  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)
  }

So, this should be rewritten using a state monad somehow. But I just don't get, how.
Trying this:

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: Updated example, according to answers.

Any good tutorials/explanations on state monads in scalaz, showing how to use gets, put, etc?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

骑趴 2024-12-27 23:58:07

警告:我从未使用过 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) 使用“old”暗语。

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

Warning: I've never used the Scala state monad. However, I think I see the reason it behaves as you say it does.

onSubmit sees the old pass, not the one, I'm put'ting

Well, look at what you are doing:

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

Firstly, I don't think you are putting what you think you're putting. Try this instead:

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

Secondly, I don't think you are getting what you think you're getting. I have no clue how Scalaz state monad works, but it should be something like this:

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

I don't think that you use pass to refer to the changing state; pass is simply the value that is given to the state computation to begin with, which would explain why User.logIn("username", pass) is using the "old" oassword.

Also (though I don't know SHtml or what & does) I highly doubt this will actually work. It's hard to explain why I think this, but it has something to do with SHtml probably not being friendly with constructing state expressions inside of itself, as Debilski commented. SHtml.password seems to expect you to give it an arbitrarily side-effecting function; this design choice immediately makes it unfriendly to a functional approach for the thing you are attempting to do.

静谧幽蓝 2024-12-27 23:58:07

到目前为止我发现的最好的 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-7/example/src/main/scala/scalaz/example/WordCount.scala

在字数统计示例中,它统计了 3 个值,并且 wordcount 值是通过使用状态计算的。我希望这有帮助。

The best scalaz examples I have found so far are these:
http://etorreborre.blogspot.com/2011/06/essence-of-iterator-pattern.html?m=1
http://etorreborre.blogspot.com/2011/12/pragmatic-io.html?m=1
And the follow ups.
This example from scalaz examples :)
https://github.com/scalaz/scalaz/blob/scalaz-seven/example/src/main/scala/scalaz/example/WordCount.scala

In the word count example it counts 3 values and the wordcount value is calculated through using state. I hope this helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文