In the following code, the last phrase I can put an in
in front. Will it change anything?
Another question: If I decide to put in
in front of the last phrase, do I need to indent it?
I tried without indenting and hugs complains
Last generator in do {…} must be an expression
import Data.Char
groupsOf _ [] = []
groupsOf n xs =
take n xs : groupsOf n ( tail xs )
problem_8 x = maximum . map product . groupsOf 5 $ x
main = do t <- readFile "p8.log"
let digits = map digitToInt $concat $ lines t
print $ problem_8 digits
Edit
Ok, so people don't seem to understand what I'm saying. Let me rephrase:
are the following two the same, given the context above?
1.
let digits = map digitToInt $concat $ lines t
print $ problem_8 digits
2.
let digits = map digitToInt $concat $ lines t
in print $ problem_8 digits
Another question concerning the scope of bindings declared in let
: I read here that:
where
Clauses.
Sometimes it is convenient to scope bindings over several guarded equations, which requires a where clause:
f x y | y>z = ...
| y==z = ...
| y<z = ...
where z = x*x
Note that this cannot be done with a let expression, which only scopes over the expression which it encloses.
My question: so, the variable digits shouldn't be visible to the last print phrase. Do I miss something here?
Best Answer
Short answer: Use
let
withoutin
in the body of a do-block, and in the part after the|
in a list comprehension. Anywhere else, uselet ... in ...
.The keyword
let
is used in three ways in Haskell.The first form is a let-expression.
This can be used wherever an expression is allowed, e.g.
The second is a let-statement. This form is only used inside of do-notation, and does not use
in
.The third is similar to number 2 and is used inside of list comprehensions. Again, no
in
.This form binds a variable which is in scope in subsequent generators and in the expression before the
|
.The reason for your confusion here is that expressions (of the correct type) can be used as statements within a do-block, and
let .. in ..
is just an expression.Because of the indentation rules of haskell, a line indented further than the previous one means it's a continuation of the previous line, so this
gets parsed as
Without indentation, you get a parse error:
In conclusion, never use
in
in a list comprehension or a do-block. It is unneccesary and confusing, as those constructs already have their own form oflet
.