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:
whereClauses.
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?
Short answer: Use
letwithoutinin the body of a do-block, and in the part after the|in a list comprehension. Anywhere else, uselet ... in ....The keyword
letis 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
inin a list comprehension or a do-block. It is unneccesary and confusing, as those constructs already have their own form oflet.