0:04Skip to 0 minutes and 4 secondsJEREMY: 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.
0:59Skip to 0 minutes and 59 secondsWhereas 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.
1:58Skip to 1 minute and 58 secondsA function is strict in its argument if when we supply bottom as that argument the function fails to terminate.
2:08Skip to 2 minutes and 8 secondsF 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.
2:23Skip to 2 minutes and 23 secondsInfinite 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.
3:21Skip to 3 minutes and 21 secondsThe 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.