-
Notifications
You must be signed in to change notification settings - Fork 4
0101: Email Tutorials ‐ Lazy Evaluation
- Email 101 – How Haskell Programs Are Executed
- Email 92 – What Is Lazy Evaluation?
- Email 93 – Benefits of Lazy Evaluation
- Email 94 – Evaluation by Applying Definitions
- Email 95 – Innermost vs Outermost Evaluation
- Email 96 – Termination and Infinite Computations
- Email 97 – Sharing and the Meaning of Laziness
- Email 98 – Infinite Lists in Practice
- Email 99 – Modular Programming with Lazy Evaluation
- Email 100 – Prime Numbers and the Sieve of Eratosthenes
- Glossary of Terms
- Quiz Questions (Table Format)
- Quiz Options (Table Format)
- Next Steps and Quiz Link
Up until now in the course, the focus has been on writing programs that are clear, concise, and correct. These are the three C’s that have guided every example so far.
However, one important question has not yet been addressed: how are Haskell programs actually executed? This final lecture introduces the execution model used by Haskell, which is known as lazy evaluation.
Rather than evaluating everything immediately, Haskell delays computation until the result is actually required. This execution strategy turns out to have several powerful consequences.
Lazy evaluation is the technique used by Haskell to evaluate expressions. Instead of eagerly computing values as soon as they appear, expressions are evaluated only when their results are needed.
This means that Haskell avoids unnecessary work. If part of a program’s result is never used, that computation is never performed.
Lazy evaluation provides four key benefits.
First, it avoids unnecessary computation, which can improve efficiency. Second, it ensures termination whenever possible, meaning that if any evaluation order can produce a result, lazy evaluation will find it. Third, it enables programming with infinite lists and infinite data structures. Finally, it allows programs to be written in a more modular way by separating control from data.
The most basic way to evaluate expressions is by repeatedly applying definitions until no further simplification is possible. This is familiar from school mathematics.
For example, if square n = n * n, then evaluating square (1 + 2) can be done by first computing 1 + 2 or by expanding the definition of square.
Both approaches lead to the same result.
There are two extreme evaluation strategies.
Innermost evaluation reduces the smallest expressions first. Outermost evaluation reduces the largest expressions first.
In a pure functional language like Haskell, all evaluation orders give the same result provided they terminate. The difference lies in whether they terminate and how much work they perform.
Consider a recursive definition such as infinity = 1 + infinity.
Using innermost evaluation, expressions involving infinity may never terminate.
However, with outermost evaluation, it is sometimes possible to obtain a result without fully expanding infinite structures. This means outermost evaluation may terminate even when innermost evaluation does not.
Outermost evaluation can duplicate work. Lazy evaluation fixes this by sharing results instead of recomputing them.
Lazy evaluation is therefore defined as outermost evaluation combined with sharing. This ensures termination whenever possible and never requires more steps than innermost evaluation.
Lazy evaluation makes infinite lists practical.
For example, the list ones = 1 : ones represents a potentially infinite list.
If a program only needs the first element, only that element is produced. The rest of the list is never evaluated.
This is why infinite lists in Haskell are potentially infinite rather than immediately infinite.
Lazy evaluation enables a powerful form of modular programming.
Programs can be split into a data-producing part and a control part.
For example, an infinite list of values can be combined with a control function such as take.
This separation makes programs clearer, more reusable, and more expressive.
The Sieve of Eratosthenes is an ancient algorithm for generating prime numbers. Using lazy evaluation, it can be implemented as a short and elegant Haskell program.
The infinite list of prime numbers is defined once, and different control functions determine how many primes are used. This includes generating the first ten primes, primes below a threshold, or even twin primes.
Lazy Evaluation An evaluation strategy where expressions are evaluated only when their results are required.
Innermost Evaluation An evaluation strategy that reduces the smallest expressions first.
Outermost Evaluation An evaluation strategy that reduces the largest expressions first.
Infinite List A list defined recursively that can produce values indefinitely when needed.
Sharing A technique where evaluated expressions are reused instead of recomputed.
Sieve of Eratosthenes An algorithm for generating prime numbers by repeatedly removing multiples.
Bernard Sibanda is a global Technology Entrepreneur, Web3 and Software Consultant with a deep focus on Cardano Blockchain, Midnight and Community building.
Key Positions:
- Founder, CTO, Developer Advocate cohort #1, Fullstake Developer, Cardano Ambassador, Catalyst Project Manager, DREP-WIMS:
- Co-founder of ABL Tech and Cardano Africa Live
- EBU-certified Plutus Pioneer (Plutus/Haskell)
- Cohort #1 Plutus Pioneer Developer
- Catalyst Community Reviewer & Funded Projects Manager
-
DRep for WIMS-Cardano (ID:
drep1yguj8zu48n99pv70yl6ckzt9hdgjy8yjnlqs2uyzcpafnjgu4vkul) - Intersect Developer Advocate
- Intersect Committe Member 2025-2026
- Cardano Marketer,Promoter and blogger
- Cardano Open Source Contributor
- Cardano communities and events organizer and builder
- Cardano Ambassador for South Africa
Official links:
- Stablecoins Dex
- Coxygen Global Universities
- WIMS Cardano Global
- Cardano Africa Live
- WIMS Cardano Videos
- Cardano Smart Contract Videos
- Fullstack IT Consulting
Social links: