Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trying to understand scalaz state monad

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?

like image 249
George Avatar asked Oct 09 '22 06:10

George


2 Answers

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.

like image 176
Dan Burton Avatar answered Oct 14 '22 03:10

Dan Burton


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.

like image 41
AndreasScheinert Avatar answered Oct 14 '22 01:10

AndreasScheinert