Re: Understanding the continuation monad's bind operator
Don't have time to go in depth on an explanation. But remember that m- bind must work with m-result according to the 3 monadic laws. This constrains what it can do. Don't know if you saw, but I did a whole tutorial on the continuation monad. It's at: http://intensivesystems.net/tutorials/cont_m.html Jim Steven E. Harris wrote: > In clojure.contrib.monads, there's a monad defined called "cont-m" to > model continuations. Its bind operator -- `m-bind` -- is defined as > follows: > > , > | (fn m-bind-cont [mv f] > | (fn [c] > | (mv (fn [v] ((f v) c) > ` > > I'm curious why there's an extra delaying wrapper function there. The > outermost `fn' form taking the argument "c" as a continuation looks like > it serves only to delay evaluation of the remaining forms. > > The parameter "mv" is a monadic value which, for the continuation monad, > is a function accepting a single continuation argument. The parameter > "f" is a monadic function which, again, for the continuation monad, is a > function accepting a value offered by a continuation and returning a > monadic value -- another function accepting a single continuation > argument. > > If all of that is true, then the form > > , > | (f v) > ` > > should evaluate to a monadic value and be suitable as a return value > from `m-bind'. In short, why is this not an acceptable implementation? > > , > | (fn m-bind-cont [mv f] > | (mv (fn [v] (f v > ` > > -- > 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
Re: Understanding the continuation monad's bind operator
On 05.01.2010, at 02:23, Steven E. Harris wrote: > , > | (fn m-bind-cont [mv f] > | (fn [c] > | (mv (fn [v] ((f v) c) > ` > > I'm curious why there's an extra delaying wrapper function there. The > outermost `fn' form taking the argument "c" as a continuation looks > like > it serves only to delay evaluation of the remaining forms. Exactly. The result of m-bind must be a continuation-accepting function again. That's the role of the outer layer (fn [c] ...). > If all of that is true, then the form > > , > | (f v) > ` > > should evaluate to a monadic value and be suitable as a return value > from `m-bind' It is indeed a value of the right type, but it is not right value that represents the composite computation. > In short, why is this not an acceptable implementation? > > , > | (fn m-bind-cont [mv f] > | (mv (fn [v] (f v > ` This version of m-bind would not return the composite computation, but rather execute it immediately. This is best seen by the position of mv. In your m-bind, mv is called when m-bind is called. That's not the desired behaviour. Konrad. -- 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
Re: Understanding the continuation monad's bind operator
Konrad Hinsen writes: > Exactly. The result of m-bind must be a continuation-accepting > function again. Yes, and invoking 'mv' yields such a function. > That's the role of the outer layer (fn [c] ...). That one adds /another/ layer, but the inner function returned by 'mv' has the same "signature", right? > It is indeed a value of the right type, but it is not right value that > represents the composite computation. Ah, now we're getting somewhere. > This version of m-bind would not return the composite computation, but > rather execute it immediately. This is best seen by the position of > mv. In your m-bind, mv is called when m-bind is called. That's not the > desired behaviour. I'm interested in what you mean by "composite computation", because I think it's hinting at some concept for monads that I missed. If, as you say, executing the function immediately is not acceptable behavior, then I infer that the goal is to delay evaluation of the monadic function 'f' until someone finally passes in a "real" continuation as, say, by the `run-cont' function. Is that right? If so, is it the case with all or most monads that the bind operator is not meant to actually perform computation on the spot, but rather to compose a delayed computation, or is this delaying particular to the continuation monad? -- 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
Re: Understanding the continuation monad's bind operator
jim writes: > Don't know if you saw, but I did a whole tutorial on the continuation > monad. Your essay is how I got started with monads in Clojure. I've read it six times now (along with five other of your essays on the subject), but perhaps I missed the requirement pertaining to delaying evaluation of the monadic function provided to bind. -- 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
Re: Understanding the continuation monad's bind operator
I have a few more questions concerning how one interacts with a continuation monad. It's clear that a monadic function accepts some "base value" and returns a monadic value, in turn being a function accepting a single continuation argument. That means that a monadic function has a signature like a -> m b Say that we're looking to use some "normal" functions with this monad. Those functions may have signatures like a -> b They clearly don't return the right kind of value. There must be some way to integrate such functions without writing new wrappers around them by hand. Is this a job for `m-fmap'? Reading the implementation, it looks like it would take a "normal" function and allow it to call on the basic value extracted from a monadic value. The lift operator also sounded relevant, but, if I understand it correctly, it converts a "normal" function to one that accepts a monadic value and returns a monadic value. That's the wrong argument type to be used with bind -- which wants to call on a monadic function with a basic value -- so I don't understand when one would want to use lift. When would one be able to call on a "lifted" function? A simple example would help. -- 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
Re: Understanding the continuation monad's bind operator
On 07.01.2010, at 01:56, Steven E. Harris wrote: I'm interested in what you mean by "composite computation", because I think it's hinting at some concept for monads that I missed. If, as you say, executing the function immediately is not acceptable behavior, then I infer that the goal is to delay evaluation of the monadic function 'f' until someone finally passes in a "real" continuation as, say, by the `run-cont' function. Is that right? Right. Consider the following simple example: (domonad cont-m [x (m-result 1) y (m-result 2)] (+ x y)) Its result is a function that, when called with a continuation argument, calls the continuation with the argument 3. This implies that nothing at all is executed when the monadic composition happens. All real execution is delayed until the composite function is called. If so, is it the case with all or most monads that the bind operator is not meant to actually perform computation on the spot, but rather to compose a delayed computation, or is this delaying particular to the continuation monad? No. The state and continuation monads behave like that, but the sequence and maybe monads do not. This is not as arbitrary as it may seem to be, as there is a simple rule: When the monadic values are functions representing computations, monadic composition yields a new function but doesn't execute anything. When the monadic values represent results of computations, then monadic composition implies execution of the computational steps. Konrad. -- 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
Re: Understanding the continuation monad's bind operator
On 07.01.2010, at 02:23, Steven E. Harris wrote: That means that a monadic function has a signature like a -> m b RIght. Say that we're looking to use some "normal" functions with this monad. Those functions may have signatures like a -> b They clearly don't return the right kind of value. There must be some way to integrate such functions without writing new wrappers around them by hand. Is this a job for `m-fmap'? There are various ways to construct monadic values. m-fmap is one of them, but it already requires a monadic value as input. The simplest way to construct a monadic value is m-result. Reading the implementation, it looks like it would take a "normal" function and allow it to call on the basic value extracted from a monadic value. Indeed. One way to define m-fmap is (defn m-fmap [f mv] (domonad [x mv] (f x))) But note that the second value is already a monadic value. The lift operator also sounded relevant, but, if I understand it correctly, it converts a "normal" function to one that accepts a monadic value and returns a monadic value. Right. For a function of a single argument, m-lift and m-fmap are equivalent. That's the wrong argument type to be used with bind -- which wants to call on a monadic function with a basic value -- so I don't understand when one would want to use lift. When would one be able to call on a "lifted" function? A simple example would help. Here is an example taken from clojure.contrib.monads.examples. The function "pairs" take a sequence of values and produces a sequences of all pairs of items in the input sequence: (with-monad sequence-m (defn pairs [xs] ((m-lift 2 #(list %1 %2)) xs xs))) Konrad. -- 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
Re: Understanding the continuation monad's bind operator
Thank you, Konrad. Your explanation was perfect. -- 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
Re: Understanding the continuation monad's bind operator
Konrad Hinsen writes: > When the monadic values are functions representing computations, > monadic composition yields a new function but doesn't execute > anything. When the monadic values represent results of computations, > then monadic composition implies execution of the computational steps. Can you recommend a book that covers aspects of monads like these? I'd like to learn more about the abstract concepts than their implementation in a particular language. -- 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
Re: Understanding the continuation monad's bind operator
On 8 Jan 2010, at 02:43, Steven E. Harris wrote: Can you recommend a book that covers aspects of monads like these? I'd like to learn more about the abstract concepts than their implementation in a particular language. I don't know about any books. There's a lot of monad material on the Web, coming mostly from the Haskell community. A good starting point are the monad-related publications by Philip Wadler: http://homepages.inf.ed.ac.uk/wadler/topics/monads.html For an introduction, look at "Monads for functional programming" and "Comprehending monads". Konrad. -- 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