Haskell - How does this average function work?

I'm not a fan of this particular pointfree-trick. It uses the Applicative (a->) instance as a “fanout”, to pass the argument to two separate functions. Essentially those two functions are sum and length, and the results are then combined back by div, which can be expressed nicely with arrow combinators (albeit a bit more verbose, because arrows don't really play in Haskell's default curried style):

import Control.Arrow

avg = uncurry div . (sum &&& length)

In the applicative trick, you merge the combining function into the first argument-sharing one. So div . sum in this case, and the result of the other function length is then passed into the second argument of the first function.

You can also use

avg = liftA2 div sum length

which uses the Applicative instance too.


<*> :: Applicative f => f (a -> b) -> f a -> f b is the sequential application function that works on an Applicative structure. For a function, this is implemented as [src]:

instance Applicative ((->) r) where
    pure = const
    (<*>) f g x = f x (g x)
    liftA2 q f g x = q (f x) (g x)

so f <*> g is short for \x -> f x (g x). This thus means that in the case of avg:

avg = div . sum <*> length

is equivalent to:

avg x = (div . sum) x (length x)

which is thus equivalent to:

avg x = div (sum x) (length x)

so it divides the sum x with length x.