Back to the front page

foo = foldl $ flip ($)

This piece of Haskell code lies on my homepage. I no longer program in Haskell, but I can still figure out what this does (though I did have to reïnstall ghc to check).

foo = foldl $ flip ($) is just an obtuse way of saying foo = foldl (flip ($)). Now foldl's signature is:

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

Or, more legibly, it takes:

Now typing

foldl (+) 44 [5, 8, 3, 5]

into ghci outputs 65 – that is, ((((44 + 5) + 8) + 3) + 5).

But in the code example on my homepage, foldl gets passed in too few arguments. That's perfectly legal, since technically speaking, all functions take only one parameter. In our case, the other two arguments to foldl can be passed into foo to get the value we want. Let's rewrite the definition to include explicit parameters:

foo seed entries = foldl (flip ($)) seed entries

And speaking of which, let's rewrite the first argument passed to foldl. $ is an operator such that f $ x = f x (and ($) is just Haskell's way of expressing that operator as a function). flip's signature is (a -> b -> c) -> b -> a -> c, and you can think of it as taking three parameters, but here it's more useful to think of it as taking a function with two parameters and returning another function that takes in those parameters in the other order.

foo seed entries = foldl (\x f -> f x) seed entries

Here, we can see that if seed has a type of b, then (\x f -> f x) takes in two arguments of b and b -> c, respectively, and spits out a c. Because of the signature of foldl, b and c have to refer to the same type. Then a in the signature shown earlier is b -> b. seed is also a b, and entries is some foldable thing (let's go with lists for now) of functions b -> b. You can verify this in ghci.

So what does this code do? The function returns the result from applying each element of entries successively on seed, so, for instance, foo x [f1, f2, f3] = f3 (f2 (f1 x)). For a concrete example:

foo 5.2 [\a -> sqrt a, \a -> 35 + a, \a -> cos (2.6 * a)]
    = (\a -> cos (2.6 * a)) ((\a -> 35 + a) ((\a -> sqrt a) 5.2))
    = (\a -> cos (2.6 * a)) ((\a -> 35 + a) (sqrt 5.2))
    = (\a -> cos (2.6 * a)) (35 + (sqrt 5.2))
    = cos (2.6 * (35 + (sqrt 5.2)))
    = -0.8958481640418573

I hate Haskell.