I am reading this tutorial on Haskell. They define function composition as the following:
(.) :: (b->c) -> (a->b) -> (a-
From the HaskellWiki page on function composition:
desort = (reverse . sort)
Now desort
is a function that sorts a list in reverse. Basically, desort
feeds it's arguments into sort
, and then feeds the return value from sort
into reverse
, an returns that. So it sorts it, and then it reverses the sorted list.
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.
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)); }
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".
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.
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).