1.2 Creating your own functions
You are not limited to the functions that Haskell provides. You can also create your own functions using the lambda notation.
> (\ a -> a + 1) 2 3 > (\ a b -> a + b) 3 4 7
Lambda notation has the form
\ inputs -> expression. The
backslash represents the greek letter lambda (λ), which comes from its
use in mathematics to represent functions. Then the inputs follow,
each given a name and separated by blank spaces. This is followed by
->, and then finally the expression that calculates
the output for the function. You can think of the inputs as slots that
are waiting to be filled with values so that the expression on the
right-hand side of the arrow can be computed. Let’s look at the first
lambda expression from above to understand how it works.
\ a -> a + 1
This function has only one input. When we apply this function to a number, that number fills the first (and only) input slot, and is assigned the name “a”. Now that the number has a name, it can be used in the expression on the right-hand side of the arrow to compute the output. Since there are no more input slots to fill, this entire lambda expression is reduced to just its output expression. All of the variables (in this case, just “a”) are then substituted by their actual values, and the final result is computed. Below is an outline of the steps for reasoning about how lambda expressions work.
-- the function is applied to some value (\ a -> a + 1) 2 -- assign variable names and reduce the expression (a + 1), where a = 2 -- substitute variables 2 + 1 -- compute the result 3
If we look at the second lambda expression from earlier, we can see it behaves in a similar way, except there are two inputs instead of one.
-- the function is applied to some value(s) (\ a b -> a + b) 3 4 -- assign variable names and reduce the expression (a + b), where a = 3, b = 4 -- substitute variables 3 + 4 -- compute the result 7
Lambda expressions (known in math as lambda abstractions) are a basic building block of Haskell programs. Try the following exercises before moving on.
Write a lambda expression that computes the square of a number (the number multiplied by itself)
There are at least two good ways to define this function. The first involves a simple multiplication.
> (\ x -> x * x) 3 9
The second way uses a power function
** provided by
Haskell. It multiplies the left-hand input by itself a number of
times equal to the right-hand input. In the following lambda
expression, the variable
x is multiplied by itself twice.
> (\ x -> x ** 2) 3 9
Write a lambda expression that computes the cube root of a
number. (Hint: use the power function
Lucky for us, the power function
** accepts fractional
numbers (as opposed to only accepting whole numbers), so we
1/3 as the exponent.
> (\ x -> x ** (1 / 3)) 8 2.0
Write a lambda expression that computes the circumference of a
circle given the radius using the formula
2π * radius. (Hint:
Haskell already has a definition for π called
Since Haskell already defines
> pi 3.141592653589793
let’s use that in our calculation.
> (\ radius -> 2 * pi * radius) 3 18.84955592153876
There is a special feature in ghci that allows us to temporarily give names to expressions, including lambda expressions.
> square = \ x -> x * x > square 3 9
And you can even overwrite previous definitions, if you wish.
> square = \x -> 4 > square 3 4
square function is obviously incorrect, because it will
always return the number
4, but you can see that the previous
definition has been overwritten. Overwriting definitions is a special
feature of ghci, and does not work in normal Haskell code. In
normal Haskell code, you can define something only once.
At some point you will want to save all of your definitions to a
file. Open your text editor and create a new file called
Lambdas.hs and type the following definitions into it. Save it
in your current directory.
add = \ a b -> a + b square = \ x -> x * x cuberoot = \ a -> a ** (1 / 3) circumference = \ radius -> 2 * pi * radius
Now in ghci, load the file using the special
> :load Lambdas.hs [1 of 1] Compiling Lambdas ( Lambdas.hs, interpreted ) Ok, one module loaded.
If you see output like in the example above, then you are ready to use your defined functions.
> add 3 4 7 > square 5 25
You can make changes to this file—perhaps adding new
definitions—and reload the file in ghci using the
> :reload Ok, one module loaded.
By now, you should be comfortable writing and understanding lambda
expressions. So it’s a good time to mention that there is an alternate
way to write your named function definitions that is slightly easier
to read. The following is a lambda expression that has been assigned
to the name
add = \ a b -> a + b
This could be written instead using an alternate syntax that removes the explicit lambda character, and replaces the arrow with an equal sign.
add a b = a + b
This is the preferred way to write named functions, and is the form that will be used throughout this book. Note that this syntax is only valid for named functions. For un-named functions you still need to use a lambda expression.
Open up your
Lambdas.hs file and rewrite the definitions to
use the alternate syntax discussed above.
add a b = a + b square x = x * x cuberoot a = a ** (1 / 3) circumference radius = 2 * pi * radius