Why is this code not constant-space?

Note that foldl' forces the accumulator to weak head normal form. Since the accumulator is a tuple it does not force the evaluation of the two elements of the tuple.

If you explicitly force the two elements you get a constant-space function:

f (a, b) c = a `seq` b `seq` (if c < a then c else a, if c > b then c else b)

In your original program you are building a tuple of the kind: (<thunk>, <thunk>) and every time f is applied you simply build a tuple with bigger and bigger thunks. When finally this is consumed by print the call to show forces the full evaluation of the tuple and all the comparisons are made at that point.

Using seq you instead force f to evaluate the comparison at that moment, and thus the thunks contained in the accumulator are evaluated before performing the comparison. Hence the result is that the thunks stored in the accumulator have constant size.

What foldl' does is simply avoid building the thunk: f (f (f ...) y) x.

An alternative solution, as suggested by Jubobs, to avoid explicitly using seq is to use a data type that has strict fields:

data Pair a b = Pair !a !b
    deriving Show

And so the code would become:

minMax :: [Int] -> Maybe (Pair Int Int)
minMax []   = Nothing
minMax (x:xs) = Just (foldl' f (Pair x x) xs)
                where
                  f (Pair a b) c = Pair (if c < a then c else a) (if c > b then c else b)

This avoids thunks altogether.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)