In fact, in some situations outermost reduction can be significantly more efficient, because it will terminate without performing unnecessary computations. Consider the following definition of a binary tree which stores values only at the leaves.
data BTree a = Nil | Leaf a | Node BTree a BTree a
We would like to compare the list of values stored at the frontiers of such trees. Let us define a function that checks whether these lists are the same for two trees.
equaltree :: BTree a -> BTree a -> Bool equaltree t1 t2 = ((leaflist t1) == (leaflist t2)) leaflist :: BTree a -> [a] leaflist Nil = [] leaflist (Leaf x) = [x] leaflist (Node t1 t2) = (leaflist t1) ++ (leaflist t2)
Checking list equality in Haskell is lazy and terminates when the first pair of nonequal elements is encountered, so the Haskell version of this function will actually construct leaflist t1 and leaflist t2 only to the extent required to show that they are not the same. Of course, if they are the same, both lists must be constructed in entirety. In an eager functional language (like ML), a similar function would first compute leaflist t1 and leaflist t2 in entirety and only then check them for equality, which is more expensive in general.