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
.