Search code examples
haskellghci

Issues with foldl in ghci


Trying this in ghci:

foldl (:) [1] [2,3,4]

which gives the following error:

<interactive>:51:7: error:
    • Couldn't match type ‘a’ with ‘[a]’
      Expected: [a] -> [[a]] -> [a]
        Actual: [a] -> [[a]] -> [[a]]
      ‘a’ is a rigid type variable bound by
        the inferred type of it :: [a]
        at <interactive>:51:1-21
    • In the first argument of ‘foldl’, namely ‘(:)’
      In the expression: foldl (:) [1] [2, 3, 4]
      In an equation for ‘it’: it = foldl (:) [1] [2, 3, 4]
    • Relevant bindings include it :: [a] (bound at <interactive>:51:1)

But the same thing works with foldr

foldr (:) [1] [2,3,4]

which outputs [2,3,4,1]

Shouldn't the foldl output (above) be [1,2,3,4]? As per my understanding, the only difference between foldl and foldr is where the accumulator is placed so I am not understanding this error.


Solution

  • The signatures of foldl and foldr` differ. Indeed:

    foldl :: Foldable f => (b -> a -> b) -> b -> t a -> b
    foldr :: Foldable f => (a -> b -> b) -> b -> t a -> b

    Notice the different order of a and b in the "fold function" (first parameter).

    This is likely to stress that foldl f z [x1, x2, …, xn] is defined as:

    foldl f z [x1, x2, …, xn] = f (… (f (f z x1) x2) …) xn

    whereas for foldr f z [x1, x2, …, xn], we get:

    foldr f z [x1, x2, …, xn] = f x1 (f x2 (… (f xn z) …))

    You thus can work with:

    foldl (flip (:)) [1] [2,3,4]

    But this will not give the same result, since we construct:

    foldl (flip (:)) [1] [2,3,4] = 4 : (3 : (2 : [1]))
                                 = [4, 3, 2, 1]