Skip main navigation

Lazy is Good

A key feature that distinguishes Haskell from other programming languages is lazy evaluation. Watch Jeremy Singer explain how laziness works.
JEREMY: In real life, laziness is frowned upon and considered to be a bad thing. However, in programming languages laziness is a feature and may be considered a good thing. Haskell is a lazy language. This means that the evaluation of expressions is delayed until their values are actually needed. The opposite is eager evaluation, which is what most programming languages implement, like C, Java, and Python. For instance, consider this expression– f applied to 1 plus 1, given this function definition f x equals 0. In an eager language, the calculation 1 plus 1 is done when the function f is invoked. This is call by value.
Whereas in a lazy language, like Haskell, the calculation 1 plus 1 is only done when the parameter value is used in the function body, known as call by need. So in a lazy language, if a parameter value is never needed then the parameter is never evaluated. Consider f x y equals y, then f 1 add 1 2 add 2 has value 4 and the calculation of 1 add 1 is never performed. Formally, we say the function f is strict in its second argument. Some values do not terminate when we try to evaluate them. The simplest non-terminating value is called bottom, written in mathematical notation as shown here. Its recursive definition in Haskell is bot equals bot.
A function is strict in its argument if when we supply bottom as that argument the function fails to terminate.
F bot 42 terminates fine since we never evaluate the first argument. On the other hand, f 42 bot loops forever, or at least until we press Ctrl-C in the GHC interactive console.
Infinite data structures. Laziness is very useful when dealing with infinite data. For example, think of the infinite list of one values. That’s an infinite list where each element is the integer one. We can define this in GHCi as follows. Let ones equal 1 cons’d onto ones. See the recursive nature of the definition here. What value is returned by head ones? Simply the integer value one. What value is returned by tail ones? An infinite list. I need to press Ctrl-C to interrupt this printing and evaluation of the expression. The same is true if I just try to evaluate the whole expression ones. I get another infinite list of one values.
The take function selects a finite number of elements from the front of a potentially infinite list. So let’s say take 3 ones and I get that, the finite list of 3 one values. The drop function drops elements from the front of the list and returns the rest of the list. Again, it’s infinite so I’m going to press Ctrl-C to interrupt the evaluation. In summary, if computations are not needed, then they won’t be evaluated. And we can compute with infinite data structures so long as we don’t traverse the structure infinitely.

Laziness is a key feature of the Haskell programming language. The main idea is that we only evaluate expressions when they are actually needed. Unlike Haskell, most programming languages implement eager evaluation.

This article is from the free online

Functional Programming in Haskell: Supercharge Your Coding

Created by
FutureLearn - Learning For Life

Reach your personal and professional goals

Unlock access to hundreds of expert online courses and degrees from top universities and educators to gain accredited qualifications and professional CV-building certificates.

Join over 18 million learners to launch, switch or build upon your career, all at your own pace, across a wide range of topic areas.

Start Learning now