Notes on function composition

function composition in haskell is achieved using the dot (.) operator.

The expression: g(f(x))g(f(x)) can be written as:

fn x = g (f x)
-- with composition
fn x = g . f x
-- or with one η-reduction:
fn = g . f 

you can use this to build more complex functions, like so:

partyBudget isAttending =
    foldr (+) 0 . map snd . filter (isAttending . fst)

to break this down, imagine passing in a list of tuples representing the names and contributions of people interested in attending a party, like this:

guests = [("John", 25.0), ("Mary", 55.0), ("Shane", 15.0)]

-- point-free partial function that takes a list of tuples,
-- extracts the first element, and checks if the name matches either john or shane
isAttending = (`elem` ["John", "Shane"]) . fst

main = print $ partyBudget isAttending guests

explanation

  • filter takes two arguments: a predicate (pred) and a list. here, the list is omitted for point-free style.
    the predicate is a composition of isAttending and fst. it works like this:
    1. fst: retrieves the first item from a tuple.
    2. isAttending: checks if the name matches “John” or “Shane”.

this gives us a filtered list of tuples where the condition is true.

  • map also takes two arguments: a function and a list.
    the function is snd (retrieves the second value from a tuple), and the list is the result of the filter.
    this gives us a list of contributions from the selected tuples.

  • foldr takes:

    1. a function ((+) here),
    2. a base value (0 here), and
    3. a list.

it reduces the list by applying the function to each element and an accumulator, starting from the base value.

result

in this example:

  1. filter gives [("John", 25.0), ("Shane", 15.0)].
  2. map extracts [25.0, 15.0].
  3. foldr computes the sum: 15.0+25.0=40.015.0+25.0=40.0

this type of composition is useful for [[η-reduction]]