尝试理解 scalaz 状态 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 中状态单子的任何好的教程/解释,展示如何使用 gets
、put
等?
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
警告:我从未使用过 Scala 状态 monad。然而,我想我明白它的行为就像你说的那样的原因。
好吧,看看你在做什么:
首先,我不知道不要认为你正在投入你认为你正在投入的东西。试试这个:
其次,我认为你没有得到你认为得到的东西。我不知道 Scalaz 状态 monad 是如何工作的,但它应该是这样的:
我不认为你使用
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.
Well, look at what you are doing:
Firstly, I don't think you are putting what you think you're putting. Try this instead:
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:
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 whyUser.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 withSHtml
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.到目前为止我发现的最好的 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.