16

I am a huge newbie to Haskell, I actually just started 10 minutes ago. I am trying to figure out how to define a variable inside a function. Lets say I have the function

foo :: Int -> Int
foo a = 
    b = a * 2
    b
-- Yes, I know, it doesn't do anything interesting

When I run it in GHCi I get a syntax error! How can you define a variable inside a function?

Bobby Tables
  • 1,154
  • 4
  • 15
  • 25

2 Answers2

31

There are two ways to do this:

foo a = b where b = a * 2
foo a = let b = a * 2 in b

In most cases, the choice between them is an aesthetic rather than technical one. More precisely, where may only be attached to definitions, whereas let ... in ... may be used anywhere an expression is allowed. Both where and let introduce blocks, making multiple internal variables convenient in both cases.

Daniel Wagner
  • 145,880
  • 9
  • 220
  • 380
  • Hey I was wondering how you would define multiple helper variables inside a function, would you do something like `where b = a * 2, c = a * 3` or would you use an entirely different "where" statement? – Eben Cowley Mar 04 '17 at 19:58
  • @EbenCowley A single `where`/`let` will do. Use `;` to separate declarations on the same line, or read about the indentation rules to use multiple lines. (This is the meaning of the last sentence of my post.) – Daniel Wagner Mar 04 '17 at 20:11
  • @DanielWagner : I am very new to haskell. so one basic question : does `foo a = b where b = a * 2` basically translates to `foo a=(/b->b)a * 2` ? – rahulaga-msft Dec 06 '19 at 12:31
  • @rahulaga_dev That's a decent first approximation, but as always the truth is a bit more complicated. One difference of between lambdas and let/where blocks that's important here is that the former make their variable monomorphic and the latter don't. For example, `foo :: (Int, Double); foo = (x, x) where x = 3` works fine, but `foo :: (Int, Double); foo = (\x -> (x, x)) 3` does not. – Daniel Wagner Dec 06 '19 at 15:28
3

Disregarding technical correctness, the answer is "sort of".

I think it's better to think of a variable as a function of zero arguments evaluating to a given value.

module Main where
import System.IO

foo :: Integer -> Integer
foo a =
  b where
    b = a * 2

main = do
  putStrLn $ show $ foo 10
Paul Nathan
  • 39,638
  • 28
  • 112
  • 212