Monad operators: multiple parameters

In a reply to an earlier question, someone told me that "do" expressions are simply syntactic sugar that expand to expressions with the >> and
= operators. I was trying to understand this (and the Monad class) better.
I see in my own experiments that this... main = do ln1 <- getLine putStrLn ln1 translates to this: main = getLine >>= \ln1 -> putStrLn ln1 However, what does this translate to?: main = do ln1 <- getLine ln2 <- getLine putStrLn (ln1 ++ ln2) -- frigidcode.com theologia.indicium.us

On Tuesday 07 June 2011, 14:30:29, Christopher Howard wrote:
In a reply to an earlier question, someone told me that "do" expressions are simply syntactic sugar that expand to expressions with the >> and
= operators. I was trying to understand this (and the Monad class) better.
I see in my own experiments that this...
main = do ln1 <- getLine putStrLn ln1
translates to this:
main = getLine >>= \ln1 -> putStrLn ln1
Shorter: getLine >>= putStrLn An expression `\x -> foo x' is equivalent to `foo', using a lambda doesn't make things clearer in such cases, only if something more complicated is done with the argument(s).
However, what does this translate to?:
main = do ln1 <- getLine ln2 <- getLine putStrLn (ln1 ++ ln2)
That desugars via getLine >>= \ln1 -> (do { ln2 <- getLine; putStrLn (ln1 ++ ln2); }) to getLine >>= \ln1 -> (getLine >>= \ln2 -> putStrLn (ln1 ++ ln2)) Note that the outer parentheses aren't necessary. do val <- foo bar baz val desugars to foo >>= \val -> do { bar; baz val; } and the you can desugar the right hand side recursively.

On 04:30 Tue 07 Jun , Christopher Howard wrote:
In a reply to an earlier question, someone told me that "do" expressions are simply syntactic sugar that expand to expressions with the >> and
= operators. I was trying to understand this (and the Monad class) better.
I see in my own experiments that this...
main = do ln1 <- getLine putStrLn ln1
translates to this:
main = getLine >>= \ln1 -> putStrLn ln1
However, what does this translate to?:
main = do ln1 <- getLine ln2 <- getLine putStrLn (ln1 ++ ln2)
It translates to: main = getLine >>= \ln1 -> getLine >>= \ln2 -> putStrLn (ln1 ++ ln2) -- Mats Rauhala MasseR

On 06/07/2011 04:54 AM, Mats Rauhala wrote:
On 04:30 Tue 07 Jun , Christopher Howard wrote:
In a reply to an earlier question, someone told me that "do" expressions are simply syntactic sugar that expand to expressions with the >> and
= operators. I was trying to understand this (and the Monad class) better.
I see in my own experiments that this...
main = do ln1 <- getLine putStrLn ln1
translates to this:
main = getLine >>= \ln1 -> putStrLn ln1
However, what does this translate to?:
main = do ln1 <- getLine ln2 <- getLine putStrLn (ln1 ++ ln2)
It translates to:
main = getLine >>= \ln1 -> getLine >>= \ln2 -> putStrLn (ln1 ++ ln2)
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
Thank you Fischer and Rauhala for your prompt and helpful responses. One final point of clarification, on a related note: am I correct in reasoning that... main = do let x = expression /remainder/ is the equivalent of... main = let x = expression in /expanded remainder/ so that, for example... main = ln1 <- getline let ln2 = "suffix" putStrLn (ln1 ++ ln2) would translate to... main = let ln2 = "suffix" in getLine >>= \ln1 -> putStrLn (ln1 ++ ln2) This above example works, but I want to be sure I haven't misunderstood any important technical points. -- frigidcode.com theologia.indicium.us

In your example, yes the two would produce the same result, but the
difference with using "let" inside of a do-block is that you have
access to variables captured inside the block. So for example if you
wanted to get input from the user, capitalize it and append a suffix ,
the following functions are equivalent :
import Data.Char(toUpper)
main = let suffix = "suffix" in
do
x <- getLine
let upperCase = map toUpper x
return (upperCase ++ suffix)
main2 = let suffix = "suffix" in
do
x <- getLine
return (map toUpper x ++ suffix)
Notice that in the "let upperCase ..." line in "main" uses "x" which
was defined within the do-block, you would not have access to "x"
outside the do-block. For reading simplicity when the whole function
is one do-block I usually stick the "let"s inside the block.
-deech
On Tue, Jun 7, 2011 at 11:42 AM, Christopher Howard
On 06/07/2011 04:54 AM, Mats Rauhala wrote:
On 04:30 Tue 07 Jun , Christopher Howard wrote:
In a reply to an earlier question, someone told me that "do" expressions are simply syntactic sugar that expand to expressions with the >> and
= operators. I was trying to understand this (and the Monad class) better.
I see in my own experiments that this...
main = do ln1 <- getLine putStrLn ln1
translates to this:
main = getLine >>= \ln1 -> putStrLn ln1
However, what does this translate to?:
main = do ln1 <- getLine ln2 <- getLine putStrLn (ln1 ++ ln2)
It translates to:
main = getLine >>= \ln1 -> getLine >>= \ln2 -> putStrLn (ln1 ++ ln2)
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
Thank you Fischer and Rauhala for your prompt and helpful responses.
One final point of clarification, on a related note: am I correct in reasoning that...
main = do let x = expression /remainder/
is the equivalent of...
main = let x = expression in /expanded remainder/
so that, for example...
main = ln1 <- getline let ln2 = "suffix" putStrLn (ln1 ++ ln2)
would translate to...
main = let ln2 = "suffix" in getLine >>= \ln1 -> putStrLn (ln1 ++ ln2)
This above example works, but I want to be sure I haven't misunderstood any important technical points.
-- frigidcode.com theologia.indicium.us
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

Also I don't really know how "let"s inside a do block desugars but I'm
guessing it's simple substitution so for example the "main" function
below probably translates to:
main3 = let suffix = "suffix" in
getLine >>= \x -> return (map toUpper x ++ suffix)
-deech
On Tue, Jun 7, 2011 at 11:58 AM, aditya siram
In your example, yes the two would produce the same result, but the difference with using "let" inside of a do-block is that you have access to variables captured inside the block. So for example if you wanted to get input from the user, capitalize it and append a suffix , the following functions are equivalent : import Data.Char(toUpper) main = let suffix = "suffix" in do x <- getLine let upperCase = map toUpper x return (upperCase ++ suffix) main2 = let suffix = "suffix" in do x <- getLine return (map toUpper x ++ suffix)
Notice that in the "let upperCase ..." line in "main" uses "x" which was defined within the do-block, you would not have access to "x" outside the do-block. For reading simplicity when the whole function is one do-block I usually stick the "let"s inside the block.
-deech
On Tue, Jun 7, 2011 at 11:42 AM, Christopher Howard
wrote: On 06/07/2011 04:54 AM, Mats Rauhala wrote:
On 04:30 Tue 07 Jun , Christopher Howard wrote:
In a reply to an earlier question, someone told me that "do" expressions are simply syntactic sugar that expand to expressions with the >> and
= operators. I was trying to understand this (and the Monad class) better.
I see in my own experiments that this...
main = do ln1 <- getLine putStrLn ln1
translates to this:
main = getLine >>= \ln1 -> putStrLn ln1
However, what does this translate to?:
main = do ln1 <- getLine ln2 <- getLine putStrLn (ln1 ++ ln2)
It translates to:
main = getLine >>= \ln1 -> getLine >>= \ln2 -> putStrLn (ln1 ++ ln2)
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
Thank you Fischer and Rauhala for your prompt and helpful responses.
One final point of clarification, on a related note: am I correct in reasoning that...
main = do let x = expression /remainder/
is the equivalent of...
main = let x = expression in /expanded remainder/
so that, for example...
main = ln1 <- getline let ln2 = "suffix" putStrLn (ln1 ++ ln2)
would translate to...
main = let ln2 = "suffix" in getLine >>= \ln1 -> putStrLn (ln1 ++ ln2)
This above example works, but I want to be sure I haven't misunderstood any important technical points.
-- frigidcode.com theologia.indicium.us
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

On Tuesday 07 June 2011, 19:01:29, aditya siram wrote:
Also I don't really know how "let"s inside a do block desugars but I'm guessing it's simple substitution
Yes. do let a = b foo bar desugars to let a = b in do { foo; bar; } (and then further to let a = b in foo >> bar). A bit more interesting are things like do x <- foo let a = b bar which desugars to foo >>= \x -> let a = b in bar and then the compiler may lift the let-binding out of the (>>=) if a) that's possible because it doesn't use any values bound in the do-block before and b) it's deemed a beneficial transformation (which I think it is, so at least with optimisations, I'd expect such lets to be floated out).
so for example the "main" function below probably translates to: main3 = let suffix = "suffix" in getLine >>= \x -> return (map toUpper x ++ suffix)
-deech
participants (4)
-
aditya siram
-
Christopher Howard
-
Daniel Fischer
-
Mats Rauhala