Skip to content
UoL CS Notes

Lecture 26-1

COMP105 Lectures

Evaluation Strategies

inc x = x + 1
square x = x * x

So square (inc 2) = (2 + 1) * (2 + 1) = 9 . How does Haskell evaluate this?

Strict Evaluation

In strict evaluation, we always apply the innermost function first:

square (inc 2)
	square (3)
	3 * 3
	9

Here we first apply inc and then apply square.

This means that when we call a function we first evaluate its argument.

This is the method that imperative languages use to evaluate functions. Haskell does not evaluate this way

Lazy Evaluation

In lazy evaluation, we always apply the outermost functions first:

square (inc 2)
	inc 2 * inc 2
	3 * 3
	9

First apply square then apply inc.

This method waits as long as possible until computing values.

In the following, nothing is computed until we ask for the value of z.

> let x = 1 + 1
> let y = x + x
> let z = y / 2
> z
2.0
> let x = 1 + undefined
> let y = x + x
> let z = y / 2
> z
*** Exception: Prelude.undefined

You can see here that the error only occurs when the binding is evaluated.

If a value is never used, it is never computed:

> let f x = 1
> f undefined
1

You can see here that the argument is not evaluated. This results in the program not crashing due to evaluating undefined.

Imperative Languages

Imperative languages are always strict:

  • So programmers know the order of their side effects.

Functional Languages

For pure functions the order of evaluation is irrelevant.

  • You always get the same answer.

  • No need to worry about side effects.

Some functional languages are strict by default:

  • ML
  • Ocaml

Others are lazy by default:

  • Haskell

Lazy vs. Strict

If strict evaluation finds an answer, the lazy evaluation fill find the same answer.

Sometimes lazy evaluation can find an answer when strict evaluation cannot:

> fst (1, 1 `div` 0)
1

A strict evaluator would crash in this example.

Sometimes lazy evaluation can be more efficient than strict:

  • Particularly if some values are computed but never used.

Lazy evaluation only ever computed a value when it is needed. This can lead to big efficiency savings:

  • When computing the the head of a doubled list.

Summary

Strict evaluation:

  • Evaluate things as soon as possible.
  • Gives certainty over order of side effects.

Lazy evaluation:

  • Evaluate things only when they are needed.
  • Potentially eliminates unneeded computation.

Exercise

  1. 1
  2. [5,10,*** Exception: divide by zero

    This is due to the fact that it evaluates last so will print the first two elements. This is opposed to crashing immediately.

  3. *** Exception: divide by zero