Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Function Composition

module Tutorial.Functions1.FunctionComposition

Functions can be combined in several ways, the most direct probably being the dot (.) operator:

export
square : Integer -> Integer
square n = n * n

times2 : Integer -> Integer
times2 n = 2 * n

squareTimes2 : Integer -> Integer
squareTimes2 = times2 . square

Give this a try at the REPL! Does it do what you'd expect?

We could have implemented squareTimes2 without using the dot operator as follows:

squareTimes2' : Integer -> Integer
squareTimes2' n = times2 (square n)

To get a better insight into how the dot operator works, let's implement our own version of it, instead called <.> to avoid name collision with the built-in dot operator:

private infixr 9 <.>
(<.>) : (b -> c) -> (a -> b) -> a -> c
f <.> g = \x => (f (g x))

We'll cover more about functions that take other functions as arguments in the next section, but for now, it suffices to know that our <.> is identical to the built-in ., and can be used the same way:

squareTimes2'' : Integer -> Integer
squareTimes2'' = times2 <.> square

It is important to note that functions chained by the dot operator are invoked from right to left: times2 . square is the same as \n => times2 (square n) and not \n => square (times2 n). This can be seen in our definition of <.>.

We can conveniently chain several functions using the dot operator to write more complex functions:

dotChain : Integer -> String
dotChain = reverse . show . square . square . times2 . times2

This will first multiply the argument by four, then square it twice before converting it to a string (show) and reversing the resulting String (functions show and reverse are part of the Idris Prelude and as such are available in every Idris program).