prosseek
prosseek

Reputation: 191159

The usage of let in Haskell

I have this code in Haskell.

import Data.List

main = do
    putStrLn $ "\nVerify if Exists in a String"
    let wordlist = ["monad", "monoid", "Galois", "ghc", "SPJ"]
    let tweet = "This is an example tweet talking about SPJ interviewing with Galois"
    print $ map (flip isInfixOf tweet) wordlist

Without the let, I have this error message: 10_things.hs:16:14: parse error on input ‘=’.

This is another code that works fine.

import Data.List

wordlist = ["monad", "monoid", "Galois", "ghc", "SPJ"]
tweet = "This is an example tweet talking about SPJ interviewing with Galois"      
main = do
    putStrLn $ "\nVerify if Exists in a String"
    print $ map (flip isInfixOf tweet) wordlist

In this case, I have error parse error (possibly incorrect indentation or mismatched brackets) with let. My question is when and when not to use let in Haskell?

Upvotes: 5

Views: 3027

Answers (3)

coffeequant
coffeequant

Reputation: 615

do notation is for monads. I am guessing you are unclear about monads.

let used inside do notation is basically binding. the do notation translates to this form

do {let x = expression; restofit} ==> let x = expression in do {restofit}

For instance this

do 
 line1 <- getLine            -- executes an action
 line2 <- getLine            -- executes an action
 let joined = line1 ++ line2 -- pure calculation; no action is executed
 return joined

This translates to

let joined = line1 ++ line2 in line1 <-getLine >> line2 <- getLine 

Upvotes: -1

Tikhon Jelvis
Tikhon Jelvis

Reputation: 68172

Haskell has two ways to introduce names: let and where.

You use let whenever you could have a normal expression. This can come up in two places: if you're defining a normal value and if you're inside do-notation. In the first case, you would use let ... in to introduce a name just within a single expression:

myFoo = let x = 10 ^ 10 in x + x

Inside do-notation, you do not need an in; instead, the let takes up a line just like a normal "statement" in do-notation. This is what your first example has:

main = do
  let x = something
  ...

The other way to introduce names is with where clauses, which go outside of expression. The top-level of your program—where you define all the globally visible names in your module—is in a where block, which is why you just write name = expression without a let. This happens because your module implicitly has

module Main where

on top even if you didn't write it yourself.

You can also write where blocks of your own in different scopes, which also let you define names without let:

foo x = ...
  where helperA = something
        helperB = something

Upvotes: 10

&#216;rjan Johansen
&#216;rjan Johansen

Reputation: 18199

Declarations/equations need to be inside either a let or a where block. The reason you don't need let at the top level of a module, is that it counts as a where block all by itself, started by its module declaration. A module which doesn't contain an explicit module header gets an implicit

module Main (main) where

at the beginning.

By the way, an indented let block can contain more than one declaration: you don't need the second let in your code as long as the equations line up vertically.

Upvotes: 12

Related Questions