
Thanks for the very clear explanation. More questions: What is the role of ">>"? How is ">>" different to ">>="? I am aware that ">>=" is used for sequencing parsers but that's all I know about it. Thanks, Paul At 22:28 13/10/2007, you wrote:
On 10/13/07, PR Stanley
wrote: Hi "do", what's its role? I know a few uses for it but can't quite understand the semantics - e.g. do putStrLn "bla bla" So, what does do, do?
In this example, do doesn't do anything. do doesn't do anything to a single expression (well, I think it enforces that its return value is a monad...). It's only when you give it multiple expressions that it "rewrites" them into more formal notation. For example:
do putStrLn "bla" putStrLn "blah"
Will be rewritten into:
putStrLn "bla" >> putStrLn "blah"
It introduces a block of "sequential actions" (in a monad), to do each action one after another. Both of these (since they're equivalent) mean print "bla" *and then* print "blah".
do also allows a more imperative-feeling variable binding:
do line <- getLine putStr "You said: " putStrLn line
Will be rewritten into:
getLine >>= (\line -> putStr "You said: " >> putStrLn line)
Looking at the do notation again: execute getLine and bind the return value to the (newly introduced) variable 'line', then print "You said: ", then print the value in the variable line.
You can think of the last line in the block as the return value of the block. So you can do something like:
do line <- do putStr "Say something: " getLine putStr "You said: " putStrLn line
In this example it's kind of silly, but there are cases where this is useful.
Luke

Disclaimer: I'm explaining all of this in terms of "actions", which are only one way of looking at monads, and the view only works for certain ones (IO, State, ...). Without futher ado... An action does two things: it has a side-effect and then it has a return value. The type "IO Int" is an I/O action which does something then returns an Int. (>>) :: m a -> m b -> m b x >> y first does x, *discards* its return value, then does y. You can see that the return value of x is discarded by the absence of the type variable a in the return value of (>>). So if you said: getLine >> putStrLn "Hello" This is an action which gets a line from the user and then throws it away, never to be retrieved again, only to print Hello. (>>=) :: m a -> (a -> m b) -> m b But what if you want to do something with the return value? That's what (>>=) is for. (>>=) takes an action on its left side and a function which returns an action on its right, and then "pipes" one into the other. getLine >>= (\x -> putStrLn x) This gets a line from the user and then executes the function on the right given the return value from getLine as an argument; i.e. x is bound to the return value of getLine. The above can also be written as: getLine >>= putStrLn Because of currying. This action echoes one line. Using this you can do more complex actions, like, for instance, adding two numbers: readLine >>= (\x -> readLine >>= (\y -> print (x + y))) Take a moment to grok that... Which you might like to write: do x <- readLine y <- readLine print (x + y) The parser sequencing thing is probably from the List monad (unless you're using Parsec or something). List was the first monad I really understood (before IO even), thanks to this great tutorial: http://www.haskell.org/haskellwiki/Monads_as_containers Luke

Luke Palmer wrote:
Using this you can do more complex actions, like, for instance, adding two numbers:
readLine >>= (\x -> readLine >>= (\y -> print (x + y)))
Take a moment to grok that...
Which you might like to write:
do x <- readLine y <- readLine print (x + y)
you can leave out the parentheses and make it similarly readable, still without "do" (at least, readable once you get used to the style, which might look almost as weird as do-notation) readLine >>= \x -> readLine >>= \y -> print (x + y) Isaac

PR Stanley wrote:
Thanks for the very clear explanation. More questions: What is the role of ">>"? How is ">>" different to ">>="? I am aware that ">>=" is used for sequencing parsers but that's all I know about it. Thanks, Paul
foo >>= bar executes the action "foo" and passes its result to the function "bar" (which must then return another action, which is executed). foo >> bar executes the action "too", and then executes the action "bar". Any result generated by "foo" is discarded, and "bar" must be an action rather than a 1-argument function that *returns* an action. Make any sense?

Andrew Coppin writes:
PR Stanley wrote:
What is the role of ">>"? How is ">>" different to ">>="? I am aware that ">>=" is used for sequencing parsers but that's all I know about it.
foo >>= bar
executes the action "foo" and passes its result to the function "bar" (which must then return another action, which is executed).
foo >> bar
executes the action "too", and then executes the action "bar". Any result generated by "foo" is discarded
=== I believe that our - sometimes helpful, sometimes not - answers should regularly encourage the newbies to *READ* the tutorials, the documentation, etc. My goodness, is it really too difficult? Then, the answer would be given by the default definition in the Prelude: -- Minimal complete definition: m >> k = m >>= \_ -> k which means exactly that, >>= is the base, >> uses it, but doesn't care about the argument. And shows that the verbal explanation, "actions", "executed", etc. may not be true in general I know that asking helpful humans is nicer than reading docs, but the latter is usually more instructive, and often more efficient. Jerzy Karczmarczuk

On 10/14/07, jerzy.karczmarczuk@info.unicaen.fr
I know that asking helpful humans is nicer than reading docs, but the latter is usually more instructive, and often more efficient.
Sorry, but from my newbie point of view, I think the docs are sometimes poor and lacking. After seeing the docs, I might want to ask the list some explanation; if I get a reply pointing me back to the doc, it doesn't help.

I'm also a Haskell no-so-new-anymore-bie, and for me, understanding monads was a question of first reading the available docs, especially http://sigfpe.blogspot.com/2006/08/you-could-have-invented-monads-and.html and http://haskell.org/haskellwiki/IO_inside, plus reading the Haskell School of Expression http://haskell.org/soe/ book, but mainly, creating some of the monad instances myself, step by step (I started with a random number generator, and ended with the list monad). I found this very useful, and I actually had to look many times to the existing solution to get it right. It made me appreciate the genius minds behind this. After a bit of practice, I can now use monads almost as easy as I can write imperative C/C++/C# code, although I find this is also the dangerous part of the do notation: you tend to forget the beautiful pure functional implementation that is behind the scenes, and start to think imperatively (again)... If you want I can dig up my old source code where I converted a random number generator from a purely functional approach to a monadic approach, but I'm not sure reading it would help you, it's creating the code yourself that will be useful I guess. Good luck, Peter Verswyvelen avid48 wrote:
On 10/14/07, jerzy.karczmarczuk@info.unicaen.fr
I know that asking helpful humans is nicer than reading docs, but the latter is usually more instructive, and often more efficient.
Sorry, but from my newbie point of view, I think the docs are sometimes poor and lacking. After seeing the docs, I might want to ask the list some explanation; if I get a reply pointing me back to the doc, it doesn't help. _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On 10/14/07, Peter Verswyvelen
If you want I can dig up my old source code where I converted a random number generator from a purely functional approach to a monadic approach, but I'm not sure reading it would help you, it's creating the code yourself that will be useful I guess.
Actually I stopped bothering long ago about 'understanding monads'. After reading many blog posts, wikis, tutorials, etc, often multiple times, I developped a fuzzy idea of what you can do using monads, and that's enough for me to use monads like IO, STM, State, Parsec, etc. without too much problems. I use haskell to solve many little problems in my job and I'm damned sad that I can't use it for larger projects. I feel I'm still a long way from identifying a situation where I would need to write my own monad, and be able to do it, but by the time such situation arises, I don't think it'd be too much a problem. That being said, I plead guilty of not provinding feeback where I found the doc lacking. I have no excuse.

Actually I stopped bothering long ago about 'understanding monads'.
I think that's a shame, because when I wrote the source code myself to get
from a pure functional approach (passing the "object" from function to
function as an extra argument) to a monadic approach, it was a real eye
opener. Many of the different FP techniques, like partial
http://www.haskell.org/haskellwiki/Partial_application application,
reversed' http://www.haskell.org/haskellwiki/Parameter_order parameter
order, lambas http://www.haskell.org/haskellwiki/Anonymous_function ,
pointfree notation http://haskell.org/haskellwiki/Pointfree etc were
required to do this, which might be one of the reasons it's a bit difficult
for newbies to see how a monad is just pure FP in disguise. After cracking
the code myself, I had so much appreciation for the guys who invented this
stuff, it's really the work of a genius, at least that's the way it felt to
me. And then the math approach to abstract the whole thing into a type
class, so it can be used for many other "single-flow" (or how should I call
that?) computations,... so nice. I can't say that I can write a monad
instance myself yet without peeking in the book, but I think I would
recognize the pattern if I see code that could make use of monads (at least
the simple cases).
Now I'm figuring out arrows, and this gives me a feeling like... euh...
well... it's even more abstract, it encapsulates any kind of computation,
also the ones then can be "split into multiple branches" (okay, I should not
talk about this, I don't really get arrows yet...)
Of course, I'm a kind of guy who likes to understand the inner details
before I'm really pleased... So for Haskell, I still have a long way to go
:)
But you seem to be much further ahead than I am when it comes to *using*
monads, so your approach is probably better. Just get used to the damn
things and accept them (ouch, that feels a lot like religion...)
Cheers,
Peter
-----Original Message-----
From: dav.vire@gmail.com [mailto:dav.vire@gmail.com] On Behalf Of david48
Sent: Monday, October 15, 2007 9:15 AM
To: bf3@telenet.be
Cc: jerzy.karczmarczuk@info.unicaen.fr; haskell-cafe@haskell.org
Subject: Re: [Haskell-cafe] do
On 10/14/07, Peter Verswyvelen
If you want I can dig up my old source code where I converted a random number
generator from a purely functional approach to a monadic approach, but I'm not
sure reading it would help you, it's creating the code yourself that will be useful I
guess.
Actually I stopped bothering long ago about 'understanding monads'. After reading many blog posts, wikis, tutorials, etc, often multiple times, I developped a fuzzy idea of what you can do using monads, and that's enough for me to use monads like IO, STM, State, Parsec, etc. without too much problems. I use haskell to solve many little problems in my job and I'm damned sad that I can't use it for larger projects. I feel I'm still a long way from identifying a situation where I would need to write my own monad, and be able to do it, but by the time such situation arises, I don't think it'd be too much a problem. That being said, I plead guilty of not provinding feeback where I found the doc lacking. I have no excuse.

On Mon, 15 Oct 2007, Peter Verswyvelen wrote:
Actually I stopped bothering long ago about 'understanding monads'.
I think that's a shame, because when I wrote the source code myself to get from a pure functional approach (passing the "object" from function to function as an extra argument) to a monadic approach,
where "monadic" is still "pure functional", but somehow tries to hide that

Yes, exactly, but how does one call the way of programming without monads / do notation then, explicitly passing the "object"? Does this approach have a name? Or just "non-monadic style"? Henning Thielemann wrote:
On Mon, 15 Oct 2007, Peter Verswyvelen wrote:
Actually I stopped bothering long ago about 'understanding monads'.
I think that's a shame, because when I wrote the source code myself to get from a pure functional approach (passing the "object" from function to function as an extra argument) to a monadic approach,
where "monadic" is still "pure functional", but somehow tries to hide that

Peter Verswyvelen writes:
Yes, exactly, but how does one call the way of programming without monads / do notation then, explicitly passing the "object"? Does this approach have a name? Or just "non-monadic style"?
In the jargon of CPS, somehow related to Monads, the constructions which do not use continuations are often called in Direct Style. I think it can be exported to Monads in general. State Monad in particular. IO is different, you *cannot* make it non-monadic. Jerzy Karczmarczuk

On Oct 15, 2007, at 7:02 , jerzy.karczmarczuk@info.unicaen.fr wrote:
IO is different, you *cannot* make it non-monadic.
Not really true; it's just much more painful. You just e.g. explicitly do what the ghc library's implementation of IO does: construct a chain of functions with an opaque (and optionally(?) existential to enforce the opacity) "RealWorld" type which is passed as state from one invocation to the next, with the "top level" application partially applied. Or one of the operationally equivalent tricks used by other Haskell runtime implementations, cf. "IO Inside". It's not so much hard as it is far too much "busywork" for a programmer to want to deal with when programming... hence hiding the scaffolding in the type, which is perhaps the most general description of what a Haskell monad actually is. -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH

On Oct 15, 2007, at 9:48 , Brandon S. Allbery KF8NH wrote:
On Oct 15, 2007, at 7:02 , jerzy.karczmarczuk@info.unicaen.fr wrote:
IO is different, you *cannot* make it non-monadic.
Not really true; it's just much more painful.
Expanding on this slightly: the neat thing about Haskell's monads is not that they are somehow not "pure". It is that they a completely pure and referentially transparent way to capture and safely encapsulate concepts that themselves may *not* be pure or referentially transparent, such as IO --- while simultaneously being useful for concepts that *are* pure and referentially transparent, such as State or Maybe/Either/[]. -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH

Yes indeed, Concurrent Clean actually just passes around the "world" object in "direct/explicit style" but uses uniquness typing to make sure nothing happens that would violate the nice FP paradigm (mainly referential transparency?). That is, I think it's like that :) -----Original Message----- From: haskell-cafe-bounces@haskell.org [mailto:haskell-cafe-bounces@haskell.org] On Behalf Of Brandon S. Allbery KF8NH Sent: Monday, October 15, 2007 3:49 PM To: jerzy.karczmarczuk@info.unicaen.fr Cc: haskell-cafe Cafe Subject: Re: [Haskell-cafe] do On Oct 15, 2007, at 7:02 , jerzy.karczmarczuk@info.unicaen.fr wrote:
IO is different, you *cannot* make it non-monadic.
Not really true; it's just much more painful. You just e.g. explicitly do what the ghc library's implementation of IO does: construct a chain of functions with an opaque (and optionally(?) existential to enforce the opacity) "RealWorld" type which is passed as state from one invocation to the next, with the "top level" application partially applied. Or one of the operationally equivalent tricks used by other Haskell runtime implementations, cf. "IO Inside". It's not so much hard as it is far too much "busywork" for a programmer to want to deal with when programming... hence hiding the scaffolding in the type, which is perhaps the most general description of what a Haskell monad actually is. -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Peter Verswyvelen writes, about non-monadic IO, after the posting of Brandon S. Allbery, who reacted to my claim that IO Monad is unavoidable:
Not really true; it's just much more painful. You just e.g. explicitly do what the ghc library's implementation of IO does: construct a chain of functions with an opaque (and optionally(?) existential to enforce the opacity) "RealWorld" type which is passed as state from one invocation to the next, with the "top level" application partially applied.
P.V.:
Yes indeed, Concurrent Clean actually just passes around the "world" object in "direct/explicit style" but uses uniquness typing to make sure nothing happens that would violate the nice FP paradigm (mainly referential transparency?). That is, I think it's like that :)
Well, I think I am one of not-so-numerous people on this list who use Clean. (After all, it is the competitor... We might forget about the buzzword "Concurrent"...) So, I know about unique *World, *FileSystem, *File, etc., I have used it for graphics and for generation of sound. But I didn't find a way to use *really* this awful "State# RealWorld" in Haskell! Somebody can show me some working examples? Jerzy Karczmarczuk

On Oct 15, 2007, at 7:02 , david48 wrote:
On 10/15/07, Peter Verswyvelen
wrote: Yes, exactly, but how does one call the way of programming without monads / do notation then, explicitly passing the "object"? Does this approach have a name? Or just "non-monadic style"?
the "painful" style ?
Explicit style, cf. my previous message? -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH
participants (9)
-
Andrew Coppin
-
Brandon S. Allbery KF8NH
-
david48
-
Henning Thielemann
-
Isaac Dupree
-
jerzy.karczmarczuk@info.unicaen.fr
-
Luke Palmer
-
Peter Verswyvelen
-
PR Stanley