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:
b
and a
, then returns something of type b
. b
. t
of a
s. This can be, for instance, a list. 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.