Re: Lift and bind (was: Understanding the continuation monad's bind operator)

2010-01-12 Thread Graham Fawcett
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)

2010-01-11 Thread Steven E. Harris
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)

2010-01-11 Thread jim
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

2010-01-08 Thread Konrad Hinsen

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

2010-01-07 Thread Konrad Hinsen

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

2010-01-07 Thread Konrad Hinsen

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

2010-01-07 Thread Steven E. Harris
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

2010-01-07 Thread Steven E. Harris
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

2010-01-06 Thread Steven E. Harris
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

2010-01-06 Thread Steven E. Harris
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

2010-01-06 Thread Steven E. Harris
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

2010-01-05 Thread Konrad Hinsen
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

2010-01-04 Thread Steven E. Harris
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

2010-01-04 Thread jim
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