Looking for an explanation of function composition

25,933

Solution 1

Function composition is a way to "compose" two functions together into a single function. Here's an example:

Say you have these functions:

even :: Int -> Bool
not :: Bool -> Bool

and you want to define your own myOdd :: Int -> Bool function using the two above.

The obvious way to do this is the following:

myOdd :: Int -> Bool
myOdd x = not (even x)

But this can be done more succinctly using function composition:

myOdd :: Int -> Bool
myOdd = not . even

The myOdd functions behave exactly the same, but the second one is created by "glue-ing" two functions together.

A scenario where this is especially useful is to remove the need for an explicit lambda. E.g:

map (\x -> not (even x)) [1..9]

can be rewritten to:

map (not . even) [1..9]

A bit shorter, less room for errors.

Solution 2

Fun side note. Function composition is the equivalent of a syllogism in logic:

All men are mortal. Socrates is a man. Therefore, Socrates is mortal.

A syllogism composes two material implications into one:

(Man => Mortal), (Socrates => Man), therefore (Socrates => Mortal)

Therefore...

(b -> c) -> (a -> b) -> (a -> c)

... which is the type of the . function.

Solution 3

The composition of f and g is a function that first applies g to its argument, then f to the value returned by g. It then returns the return value of f.

This identity may be enlightening:

f (g x) = (f . g) x

If you have a Java/C background, consider this example:

int f(int x);
int g(int x);
int theComposition(int x) { return f(g(x)); }

Solution 4

This example is contrived, but suppose we have

sqr x = x * x  
inc x = x + 1

and we want to write a function that computes x^2+1. We can write

xSquaredPlusOne = inc . sqr

(which means

xSquaredPlusOne x = (inc . sqr) x

which means

xSquaredPlusOne x = inc(sqr x)

since f=inc and g=sqr).

Solution 5

Function composition is a way to chain two or more functions together. It's often likened to shell piping. For example, in a Unix-style shell, you might write something like

cat foo.txt | sort -n | less

This runs cat, feeds its output to sort, and feeds the output from that to less.

Strictly, this is like the Haskell $ operator. You might write something like

sum $ sort $ filter (> 0) $ my_list

Notice that, unlike the shell example, this reads from right to left. So we start with my_list as input, then we run filter over it, then we sort it, and then we calculate the sum of it.

The function composition operator, ., does something similar. The example above produces a number; the example below produces a function:

sum . sort . filter (> 0)

Notice that we didn't actually feed a list into this. Instead, we've just created a new function, and we can feed several different lists to that function. For example, you might name this function:

my_function = sum . sort . filter (> 0)

Or you might pass it as an argument to another function:

map (sum . sort . filter (> 0)) my_lists

You can basically use it anywhere that you can use any other sort of function. It's just a quick and readable way of saying "I want to chain these functions together".

Share:
25,933
Fragsworth
Author by

Fragsworth

Developer of Clicker Heroes, Cloudstone, and other games http://www.clickerheroes.com/ http://www.kongregate.com/games/nexoncls/cloudstone http://armorgames.com/cloudstone-game/15364

Updated on July 18, 2022

Comments

  • Fragsworth
    Fragsworth almost 2 years

    I am reading this tutorial on Haskell. They define function composition as the following:

    (.)                     :: (b->c) -> (a->b) -> (a->c)
    f . g                   = \ x -> f (g x)
    

    No examples were provided, which I believe would enlighten me as to what is being defined here.

    Can someone provide a simple example (with explanation) of how function composition is used?