Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Haskell, what is the difference between using and not using let?

Tags:

haskell

Someone told me Haskell does not have variables but bindings. Now what ever that means, I always wondered what the difference is when writing these bindings, like so:

x = 5

and

let x = 5

What is the difference here?

And a followup question: Am I even creating variables by doing this? If x is not a variable, what is it?

like image 238
user5846939 Avatar asked Feb 22 '17 23:02

user5846939


People also ask

What does let in Haskell do?

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.

What does () mean in Haskell?

() is very often used as the result of something that has no interesting result. For example, an IO action that is supposed to perform some I/O and terminate without producing a result will typically have type IO () .

How do I change the value of a variable in Haskell?

You can't. Once a variable has a value, it has that value forever.

What does just mean in Haskell?

It represents "computations that could fail to return a value". Just like with the fmap example, this lets you do a whole bunch of computations without having to explicitly check for errors after each step.


2 Answers

The only real difference is where they occur.

-- At top (file) level or in "where" blocks, omit "let".
x = 5

f1 y = x + y
  where
    x = 5

-- Inside expressions or do-blocks, "let" is required.
f2 y = let x = 5
       in x + y

f3 y = do someAction
          let x = 5
          return (x + y)

In all cases, x is a variable. However, you cannot change (mutate) the value of the variable.

In the GHCi prompt, it seems like you change the value of a variable, but you cannot. You can only create new variables with the same name, the old variables still exist.

Prelude> let x = 3
Prelude> let f y = x + y
Prelude> let x = 10
Prelude> f 1
4

If you had really changed the value of x, then f 1 would be 11.

like image 52
Dietrich Epp Avatar answered Oct 17 '22 09:10

Dietrich Epp


Haskell has variables, but we say they are bound rather than assigned. These are extremely similar notions, but they differ in whether they support multiple assignment - Haskell does not.

do let x = 1
   let x = 2
   print x     -- prints "2"

When we say it does not, what we mean is that all variables are bound statically. This means that any time there's a reference to a variable, you can look back up through the code and find the one binding that it refers to.

Take, for example, Python, which does have multiple assignment.

def f(a):
    x = 1          # first assignment
    x = 2          # second assignment

    for i in a:
        x = i      # third assignment
        print x 

    print x

In the above example, there are three places where x is assigned. When we refer to x on the last line, we could be getting the 2 from the second assignment, or we could be getting one of the values from a from the assignment in the loop. Whether the third assignment took place depends on whether a was empty or not.

So let's look at similar code in Haskell:

f a = do let x = 1                    -- first binding
         let x = 2                    -- second binding
         for_ a $ \i -> do let x = i  -- third binding
                           print x
         print x

The final line of this output will always be "2", because at that point in the code, the second binding is the innermost binding that x received in that scope. If we were to introduce another closer binding, then we could change that:

f a = do let x = 1                    -- first binding
         let x = 2                    -- second binding
         for_ a $ \i -> do let x = i  -- third binding
                           print x
         let x = head a               -- fourth binding
         print x

But what we can never do is introduce ambiguity about which binding something refers to.

like image 33
Chris Martin Avatar answered Oct 17 '22 07:10

Chris Martin