Values with let and where

Contents
let in an expression
where under a function
No assignment
Scope and shadowing

let in an expression

let introduces names for the expression that follows in. It is an expression, so it can sit anywhere a value can:

total = let price = 12 qty = 3 in price * qty -- 36

At the GHCi prompt the in part is optional, because the session keeps the binding for the next line. In a file it is required.

where under a function

A where clause attaches helper names to a function definition. The body reads top down, and the details sit below where they do not interrupt it:

area :: Double -> Double -> Double area w h = w * h + trim where -- both names are visible in the body above trim = 0.0

A helper used by several equations of the same function is written once in the where block, and every equation sees it.

No assignment

There is no statement that changes a value. A name is bound once, and the binding never changes. This code does not do what it looks like it does:

x = 1 x = 2 -- error: conflicting definitions of x

To get a new value, compute a new one and give it a new name. When a loop seems necessary, recursion or a fold replaces it, which is the subject of lesson 17.

Scope and shadowing

An inner binding may reuse an outer name. The inner one wins for the rest of its block, and the outer one is untouched outside:

x = 10 f = let x = 20 in x + 1 -- 21 g = x + 1 -- 11

Shadowing is legal but rarely kind to readers. Use it for short intermediate values, not for renaming a parameter in the middle of a long function.

Next: Types and type signatures

Article author: Arthur Isaev

Related articles
Haskell
Haskell course: zero to hero in 50 lessons
What is Haskell and why it matters
Install the toolchain with GHCup
GHCi: the interactive shell
Your first program
Values with let and where
Types and type signatures
Functions and application
Currying and partial application
Operators, sections, and fixity
if, guards, and pattern guards
case expressions
Pattern matching
Tuples
Lists
Ranges and enumeration
List comprehensions
Recursion replaces loops
map, filter, and foldr
Lambdas and composition
Type classes
Parametric polymorphism
Maybe and null safety
Either and recoverable errors
data: product types
data: sum types
Records
newtype and type synonyms
Recursive data: binary trees
Functor
Applicative
Monad
do notation
IO and purity
Files and IO
Modules and imports
Cabal projects
Dependencies
Testing with HUnit
Property testing with QuickCheck
Laziness and infinite lists
Strictness and space leaks
Folds
Monoids
Traversable
Monad transformers
Errors and exceptions
Concurrency
Parsing with Megaparsec
Capstone: a todo CLI
Hero roadmap: the whole course on one page

Search this site

Channel @aofeed Chat @aofeedchat

Contacts and cooperation:
I recommend our hosting beget.com
Write to info@aredel.com if you:
1. Want to write an article for our site or translate an article into your native language.
2. Want to place thematically relevant ads on the site.
3. Ads on my site pass maximum censorship. If you see an ad block unsuitable for school-age children, shocking or misleading - please contact us by e-mail
4. Found a mistake, inaccuracy, bug, etc. on the site. ... .......
5. Articles can be shared on social media by clicking a network icon: