I've been comparing the definition of the Clojure's state monad -- state-m in clojure.contrib.monads -- to definitions I've found elsewhere, and there's a facet of the Clojure definition that's puzzling: Why do monadic functions in state-m only accept one argument (a "basic value") and return a monadic value (a function accepting a state), as opposed to accepting both the "basic value" and a state?
Looking at the definitions for the state monad in Haskell, it seems ambiguous as to whether the monadic functions accept one or two values, but then functions in Haskell can all be curried, so it's hard to tell. The paper "Monads for functional programming"¹ by Philip Wadler shows the following definition of the bind operator on page 9: m * k = \X.let (a, y) = m x in let (b, z) = k a y in (b, z) Note the application of function "k" is shown as k a y where "a" is the basic value resulting from "m" and "y" is the state as updated last by "m". This definition suggests that function "k" doesn't make much sense without these two arguments supplied. Again, though, this is Haskell, so supplying multiple arguments at once doesn't mean much. In the Haskell tutorial's article "The State monad"², the definition looks more like Clojure's: (State x) >>= f = State $ \s -> let (v,s') = x s in runState (f v) s' There we see monadic function "f" applied to basic value "v", and then the result applied to the pending state "s'". Clojure's definition is as follows: (fn m-bind-state [mv f] (fn [s] (let [[v ss] (mv s)] ((f v) ss)))) There, similarly, monadic function "f" is applied first to basic value "v", and then the result applied to the pending state "ss". My question: What's the benefit of having the monadic function accept only the basic value, deferring consideration of the state, as opposed to having it accept both the basic value and the pending state together? As I write this, I realize that following Clojure's definition ensures that "monadic functions return monadic values", and here a monadic value is a function that accepts a state. What's been difficult, though, is actually writing monadic functions for use in the state monad. It feels wrong to define a function whose outcome depends both on the input basic value and the input state, but to have to "cut the function in half", receiving the two values as separate steps. Sometimes the function depends only upon the input value, in which case the `m-result' is sufficient to provide the resulting monadic value. Sometimes the function depends on both the input value and the state, in which case we have to just close over the input value and defer its consideration until we receive the state later. What would be lost by defining Clojure bind operator like this: (fn m-bind-state [mv f] (fn [s] (let [[v ss] (mv s)] (f v ss)))) Is there more to it than, "Monadic functions must return monadic values"? Any clarifying advice would be welcome. Footnotes: ¹ http://homepages.inf.ed.ac.uk/wadler/papers/marktoberdorf/baastad.pdf ² http://www.haskell.org/all_about_monads/html/statemonad.html -- Steven E. Harris -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en