Want to keep learning?

This content is taken from the The University of Glasgow's online course, Functional Programming in Haskell: Supercharge Your Coding. Join the course to learn more.

Skip to 0 minutes and 4 seconds 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.

Skip to 0 minutes and 59 seconds 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.

Skip to 1 minute and 58 seconds A function is strict in its argument if when we supply bottom as that argument the function fails to terminate.

Skip to 2 minutes and 8 seconds 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.

Skip to 2 minutes and 23 seconds 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.

Skip to 3 minutes and 21 seconds 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.

Lazy is Good

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.

Share this video:

This video is from the free online course:

Functional Programming in Haskell: Supercharge Your Coding

The University of Glasgow

Get a taste of this course

Find out what this course is like by previewing some of the course steps before you join: