Re: Lift and bind (was: Understanding the continuation monad's bind operator)
Hi, On Mon, Jan 11, 2010 at 8:44 PM, Steven E. Harris s...@panix.com wrote: Konrad Hinsen konrad.hin...@fastmail.net writes: For a function of a single argument, m-lift and m-fmap are equivalent. In Jim Duey's essay Higher Level Monads¹, he writes the following on the lift operator: ,[ m-lift ] | If you have a function that you would like to turn into a monadic | function, that is a function that can be passed to m-bind, you use | m-lift. | | m-lift takes two parameters, a function to lift and the number of | arguments that function accepts. The argument count is the first | parameter and the function is second. The return value is a function | that can be passed to m-bind. ` Isn't it the case, though, that a lifted function /can't/ be passed to bind, because it's not a monadic function? A lifted function takes monadic values as input, rather than a basic value. Is there some operator that converts a normal function a - b to a monadic function a - m b such that one could adapt a normal function for use in and among some other monadic functions (such as with m-chain)? I'm not sure such a translation is possible for all monads. I don't know Clojure monads, but in Haskell that operator would be (.) return, that is the partial application of the composition function to the 'return' function: Prelude :t (.) return (.) return :: (Monad m) = (a - b) - a - m b I considered something like this , | (defn as-monadic-fn [f] | (fn [v] | (m-result (f v I'd say that looks right. It has the same meaning as: (def as-monadic-fn (partial comp m-result)) ...which is a transliteration of (.) return in Haskell. Best, Graham but it looks too simple. Footnotes: ¹ http://intensivesystems.net/tutorials/monads_201.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 -- 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
Lift and bind (was: Understanding the continuation monad's bind operator)
Konrad Hinsen konrad.hin...@fastmail.net writes: For a function of a single argument, m-lift and m-fmap are equivalent. In Jim Duey's essay Higher Level Monads¹, he writes the following on the lift operator: ,[ m-lift ] | If you have a function that you would like to turn into a monadic | function, that is a function that can be passed to m-bind, you use | m-lift. | | m-lift takes two parameters, a function to lift and the number of | arguments that function accepts. The argument count is the first | parameter and the function is second. The return value is a function | that can be passed to m-bind. ` Isn't it the case, though, that a lifted function /can't/ be passed to bind, because it's not a monadic function? A lifted function takes monadic values as input, rather than a basic value. Is there some operator that converts a normal function a - b to a monadic function a - m b such that one could adapt a normal function for use in and among some other monadic functions (such as with m-chain)? I'm not sure such a translation is possible for all monads. I considered something like this , | (defn as-monadic-fn [f] | (fn [v] | (m-result (f v ` but it looks too simple. Footnotes: ¹ http://intensivesystems.net/tutorials/monads_201.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
Re: Lift and bind (was: Understanding the continuation monad's bind operator)
You know, I think you're right. I would refer you to part 2 of Konrad's monad tutorial, but the link is broken. Check google's cache, if you want to read an explanation immediately. I'll have to go change that. Thanks for pointing it out and sorry for any confusion. Jim Steven E. Harris wrote: Konrad Hinsen konrad.hin...@fastmail.net writes: For a function of a single argument, m-lift and m-fmap are equivalent. In Jim Duey's essay Higher Level Monads¹, he writes the following on the lift operator: ,[ m-lift ] | If you have a function that you would like to turn into a monadic | function, that is a function that can be passed to m-bind, you use | m-lift. | | m-lift takes two parameters, a function to lift and the number of | arguments that function accepts. The argument count is the first | parameter and the function is second. The return value is a function | that can be passed to m-bind. ` Isn't it the case, though, that a lifted function /can't/ be passed to bind, because it's not a monadic function? A lifted function takes monadic values as input, rather than a basic value. Is there some operator that converts a normal function a - b to a monadic function a - m b such that one could adapt a normal function for use in and among some other monadic functions (such as with m-chain)? I'm not sure such a translation is possible for all monads. I considered something like this , | (defn as-monadic-fn [f] | (fn [v] | (m-result (f v ` but it looks too simple. Footnotes: ¹ http://intensivesystems.net/tutorials/monads_201.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
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
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 konrad.hin...@fastmail.net 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
Konrad Hinsen konrad.hin...@fastmail.net 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 jim.d...@gmail.com 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 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
Understanding the continuation monad's bind operator
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
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