Function declarations in Haskell rely less on parentheses and more on whitespace relative to many other languages.
Here we define a function which returns a number that is one greater than its argument.
A basic function definition begins with:
- the name of the function (in this case,
next
), followed by a space; - the parameters (here just one parameter,
x
).
Function and parameter names begin with lowercase letters.
= x + 1 next x
If there is more than one parameter, they are separated with whitespace. This hypotenuse function requires two arguments, x
and y
.
= sqrt (x^2 + y^2) hypotenuse x y
In many cases, annotating a function definition with its type is unnecessary. In greet
, the compiler can infer that since we are concatenating the argument called name
with a string, then the type of name
must be String
and the result returned from the function is also a String
.
= "hello" ++ " " ++ name greet name
But explicit type annotations are often useful.
- The function name is followed by
::
- the type of each parameter is given followed by an arrow;
- the final type is the return type.
greet2
takes one String
argument, referred to in the function definition by the parameter name
, and returns one String
result.
Type names always begin with an uppercase letter.
greet2 :: String -> String
= "hello" ++ " " ++ name greet2 name
Functions can return multiple values. The greetNext
function returns a tuple of two values:
next x
greet (show (next x))
= (next x, greet (show (next x))) greetNext x
Pattern matching is another useful way to define functions. Here we define a function called hello
that has three cases:
- the first applies only when the argument is
"Olafur"
; - the second when the argument is
"Rocamadour"
; - the third is a fallback that matches anything else.
hello :: String -> String
"Olafur" = "hello, Olafur!"
hello "Rocamadour" = "hey!"
hello = greet x hello x
=
main do
The show
function converts values that are not strings into strings that we can print to the screen or otherwise use in string-manipulating functions.
putStrLn (show (next 4))
putStrLn (show (next (next 4)))
putStrLn (show (hypotenuse 3 4))
Since greet
and greet2
already return String
values, we do not need to use show
here.
putStrLn (greet "world")
putStrLn (greet2 "world")
We can treat the result from greetNext
as a single value.
putStrLn (show (greetNext 7))
Or we can immediately destructure it and give names (x
and y
) to its two constituent parts.
let (x, y) = greetNext 7
putStrLn (show x)
putStrLn y
putStrLn (hello "Olafur")
putStrLn (hello "Rocamadour")
putStrLn (hello "Jane")
$ runhaskell functions.hs
5
6
5.0
hello world
hello world
(8,"hello 8")
8
hello 8
hello, Olafur!
hey! hello Jane
Next: If-then-else