How to replace failure by a list of successes is a classic paper which shows the power of lazy evaluation with respect to exception handling, backtracking and pattern matching. It says we don’t need special language constructs because these features can be emulated only with lazy evaluation.

The idea is simple. Each term that may raise an exception of backtrack is replaced by a term that returns a list of values; `[]`

for failure and a singleton list for success.

- (failure) -> []
- (success) -> [v]

A term that might return many values through backtracking is replaced by a term that returns a list of those values.

- (backtracking) -> [v1, v2, …]

There are two ways of combining terms that may raise exceptions or backtrack.

“or” combination is a way of combining two terms so that evaluation of the resulting term succeeds whenever evaluation of the first term

orthe second term succeeds.

“or” combination can be implemented with list append, `(++)`

.

“and” combination is a way of combining two terms so that evaluation of the resulting term succeeds whenever evaluation of the first term

andthe second term succeeds.

“and” combination can be implemented with cartesian product.

Let’s look at an example. `assoc`

is a function that looks up entries in an association list. Given a list of pairs `xys`

and a value `x`

, the call `assoc xys x`

returns `y`

such that the pair `(x, y)`

is in the list `xys`

. If there is no such `y`

, the call should raise an exception. `assoc`

can be written in Haskell using list comprehension:

`assoc xys x = [y | (x', y) <- xys, x' == x]`

Here are the results of some experiments on assoc.

- assoc [(“a”, 1), (“a”, 3)] “a” = [1,3]
- assoc [(“a”, 1), (“b”, 2)] “b” = [2]
- assoc [(“a”, 1), (“b”, 2)] “c” = [0]

“Or” combinator `(assoc xys1 x) ? (assoic xys2 x)`

can be written

`assoc xys1 x ++ assoc xys2 x`

and “and” combinator `(assoc xys x) + (assoic xys2 x)`

can be written

`[y1 + y2 | [y1 <- assoic xys1 x, y2 <- assoc xys2 x]`

Backtracking usually requires special language features such as coroutines or generators because evaluation of an expression needs to be *suspended* after it has returned one value, and then may be *resumed* later if more values are needed. Lazy evaluation provides this property without any additional language features. That is, evaluation of a list is already performed only when more elements are needed.