Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Haskell, when do we use in with let?

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?

like image 717
McBear Holden Avatar asked Nov 25 '11 22:11

McBear Holden


People also ask

What is let in in Haskell?

In Haskell let, binding is used to bind the variables, which are very local. In Haskell, we can define any type of variable using let keyword before the variable name in Haskell. But their scope is local, we also have let in Haskell which is another form of defining the variable and use them after it.

Where vs let in Haskell?

It is important to know that let ... in ... is an expression, that is, it can be written wherever expressions are allowed. In contrast, where is bound to a surrounding syntactic construct, like the pattern matching line of a function definition.

What does in do in Haskell?

in goes along with let to name one or more local expressions in a pure function.

When should I use guards in Haskell?

Haskell guards are used to test the properties of an expression; it might look like an if-else statement from a beginner's view, but they function very differently. Haskell guards can be simpler and easier to read than pattern matching .


1 Answers

Short answer: Use let without in in the body of a do-block, and in the part after the | in a list comprehension. Anywhere else, use let ... in ....


The keyword let is used in three ways in Haskell.

  1. The first form is a let-expression.

    let variable = expression in expression 

    This can be used wherever an expression is allowed, e.g.

    > (let x = 2 in x*2) + 3 7 
  2. The second is a let-statement. This form is only used inside of do-notation, and does not use in.

    do statements    let variable = expression    statements 
  3. The third is similar to number 2 and is used inside of list comprehensions. Again, no in.

    > [(x, y) | x <- [1..3], let y = 2*x] [(1,2),(2,4),(3,6)] 

    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

do let x = 42 in      foo 

gets parsed as

do (let x = 42 in foo) 

Without indentation, you get a parse error:

do (let x = 42 in)    foo 

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 of let.

like image 178
hammar Avatar answered Oct 06 '22 23:10

hammar