Couple of questions about *let* within *do*

From: Learn You a Haskell =================== Remember let bindings? If you don't, refresh your memory on them by reading this section. They have to be in the form of let bindings in expression, where bindings are names to be given to expressions and expression is the expression that is to be evaluated that sees them. We also said that in list comprehensions, the in part isn't needed. Well, you can use them in do blocks pretty much like you use them in list comprehensions. Check this out: import Data.Char main = do putStrLn "What's your first name?" firstName <- getLine putStrLn "What's your last name?" lastName <- getLine let bigFirstName = map toUpper firstName bigLastName = map toUpper lastName putStrLn $ "hey " ++ bigFirstName ++ " " ++ bigLastName ++ ", how are you?" =================== Questions: 1) Is there an implicit *in* before the last line above? 2) Within a do "in" the IO monad (or any other monad), can a *let* do something like this? let x = do -- in a different monad Michael

On Tue, Aug 10, 2010 at 1:40 PM, michael rice
1) Is there an implicit *in* before the last line above?
The (let ... in ...) construct is an expression, while the (let ...) inside 'do' is a statement. The (do ...) itself is an expression. See the report: http://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-440003.12 http://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-470003.14
2) Within a do "in" the IO monad (or any other monad), can a *let* do something like this?
let x = do -- in a different monad
Yes =). For example,
main = do -- IO monad putStrLn "Hello!" let x = do i <- [1..5] -- list monad (i.e. []) j <- [i..5] return (i*j) mapM print x
-- Felipe.

The let's aren't really statements, they're just named expressions and are still subject to lazy evaluation. In: let x = putStrLn "Name" >> getLine putStrLn "Welcome" x The program will print: Welcome Name? and then prompt for input, even though the let comes first. And if you never ran the 'x' action, then the user would just see "Welcome" and the block of code would finish (because lazy evaluation still applies). On Tuesday Aug 10, 2010, at 12:49 PM, Felipe Lessa wrote:
The (let ... in ...) construct is an expression, while the (let ...) inside 'do' is a statement. The (do ...) itself is an expression.

Yes, and yes :)
For example:
import Data.Char
main = do
let prompt s = do
putStrLn s
getLine
firstName <- prompt "What's your first name?"
lastName <- prompt "What's your last name?"
let bigFirstName = map toUpper firstName
bigLastName = map toUpper lastName
putStrLn $ "hey " ++ bigFirstName ++ " " ++ bigLastName ++ ", how are
you?"
- Job
On Tue, Aug 10, 2010 at 12:40 PM, michael rice
From: Learn You a Haskell
===================
Remember let bindings? If you don't, refresh your memory on them by reading this section. They have to be in the form of let bindings in expression, where bindings are names to be given to expressions and expression is the expression that is to be evaluated that sees them. We also said that in list comprehensions, the in part isn't needed. Well, you can use them in do blocks pretty much like you use them in list comprehensions. Check this out:
import Data.Char
main = do putStrLn "What's your first name?" firstName <- getLine putStrLn "What's your last name?" lastName <- getLine let bigFirstName = map toUpper firstName bigLastName = map toUpper lastName putStrLn $ "hey " ++ bigFirstName ++ " " ++ bigLastName ++ ", how are you?"
===================
Questions:
1) Is there an implicit *in* before the last line above?
2) Within a do "in" the IO monad (or any other monad), can a *let* do something like this?
let x = do -- in a different monad
Michael
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

OK, then there's also an implicit *in* after the *let* in this code. Must the implicit (or explicit) *in* actually use the calculated value(s)?
And, the monad can "continue on" after the *let* (with or without the *in*) as below, i.e., the *let* needn't be the last statement in the *do*?
main = do
gen <- getStdGen
let code = genCode gen
putStrLn $ "Code is " ++ show code
putStrLn "..."
Michael
--- On Tue, 8/10/10, Job Vranish

michael rice wrote:
OK, then there's also an implicit *in* after the *let* in this code.
If you want to understand let statements in terms of let ... in ... expressions, you can do the following transformation: do s1 s2 let x1 = e1 x2 = e2 s3 s4 becomes do s1 s2 let x1 = e1 x2 = e2 in do s3 s4 So in a sense, there is an implicit "in do".
Must the implicit (or explicit) *in* actually use the calculated value(s)?
No. By the way, note that lazy evaluation applies, so the expressions bound in the let may or may not be evaluated, depending on the rest of the program.
And, the monad can "continue on" after the *let* (with or without the *in*) as below, i.e., the *let* needn't be the last statement in the *do*?
Yes, there can be more statements after the let statement. In fact, the let statement must not be the last statement in the do-expression, because a do-expression has to end with an expression statement. Otherwise, what would the result of the do-expression be? Tillmann

Hi all,
Thanks. I think I've got it. It nice to have come far enough with this to be thinking about how the pieces fit together. One more question:
Since
do s1
s2
let x1 = e1
x2 = e2
s3
s4
becomes
do s1
s2
let x1 = e1
x2 = e2 in do s3
s4
Then,
do s1
s2
let x1 = e1
x2 = e2
s3
s4
let x3 = e3
x4 = e4
s5
s6
becomes
do s1
s2
let x1 = e1
x2 = e2 in do s3
s4
let x3 = e3
x4 = e4 in do s5
s6?
Michael
--- On Tue, 8/10/10, Tillmann Rendel
OK, then there's also an implicit *in* after the *let* in this code.
If you want to understand let statements in terms of let ... in ... expressions, you can do the following transformation: do s1 s2 let x1 = e1 x2 = e2 s3 s4 becomes do s1 s2 let x1 = e1 x2 = e2 in do s3 s4 So in a sense, there is an implicit "in do".
Must the implicit (or explicit) *in* actually use the calculated value(s)?
No. By the way, note that lazy evaluation applies, so the expressions bound in the let may or may not be evaluated, depending on the rest of the program.
And, the monad can "continue on" after the *let* (with or without the *in*) as below, i.e., the *let* needn't be the last statement in the *do*?
Yes, there can be more statements after the let statement. In fact, the let statement must not be the last statement in the do-expression, because a do-expression has to end with an expression statement. Otherwise, what would the result of the do-expression be? Tillmann

On Tue, Aug 10, 2010 at 11:01:28AM -0700, michael rice wrote:
Hi all,
Then,
do s1 s2 let x1 = e1 x2 = e2 s3 s4 let x3 = e3 x4 = e4 s5 s6
becomes
do s1 s2 let x1 = e1 x2 = e2 in do s3 s4 let x3 = e3 x4 = e4 in do s5 s6?
do s1 s2 let x1 = e1 x2 = e2 in do s3 s4 let x3 = e3 x4 = e4 in do s5 s6 HTH, Alex

So all the Xs would be in scope at s6. Important point.
Thanks,
Michael
--- On Tue, 8/10/10, Alex Stangl
Hi all,
Then,
do s1 s2 let x1 = e1 x2 = e2 s3 s4 let x3 = e3 x4 = e4 s5 s6
becomes
do s1 s2 let x1 = e1 x2 = e2 in do s3 s4 let x3 = e3 x4 = e4 in do s5 s6?
do s1 s2 let x1 = e1 x2 = e2 in do s3 s4 let x3 = e3 x4 = e4 in do s5 s6 HTH, Alex

On Tuesday 10 August 2010 19:12:57, michael rice wrote:
OK, then there's also an implicit *in* after the *let* in this code.
Yes. do let x = foo bar baz is desugared to let x = foo in (bar >> baz)
Must the implicit (or explicit) *in* actually use the calculated value(s)?
No, and if the values aren't used, they're not calculated (unless you force the calculation in the bindings, e.g. with bangs).
And, the monad can "continue on" after the *let* (with or without the *in*) as below, i.e., the *let* needn't be the last statement in the *do*?
It *mustn't* be the last statement; the last statement in a do-block must be an expression (return blah, putStrLn whatever, ...)
main = do gen <- getStdGen let code = genCode gen putStrLn $ "Code is " ++ show code putStrLn "..."
Michael

michael rice wrote:
OK, then there's also an implicit *in* after the *let* in this code. Must the implicit (or explicit) *in* actually use the calculated value(s)?
And, the monad can "continue on" after the *let* (with or without the *in*) as below, i.e., the *let* needn't be the last statement in the *do*?
More specifically, there is an implicit "in do". So given some code, foo = do something let x = bar y = baz thingsome somesome First there's the insertion of braces and semicolons implied by the layout rules. foo = do { something ; let { x = bar ; y = baz }; thingsome ; somesome } Then we desugar the let-do notation, foo = do { something ; let { x = bar ; y = baz } in do { thingsome ; somesome }} Or with prettier typesetting, foo = do { something ; let { x = bar ; y = baz } in do { thingsome ; somesome } } and finally we can desugar do notation into (>>=), (>>), and fail. -- Live well, ~wren
participants (8)
-
Alex Stangl
-
Bill Atkins
-
Daniel Fischer
-
Felipe Lessa
-
Job Vranish
-
michael rice
-
Tillmann Rendel
-
wren ng thornton