Skip to content
AgileLogics
5 min read

Defining Functions

Prerequisites: Types and type inference

A function definition is the function name, its parameters, =, and an expression for the result:

square :: Int -> Int
square x = x * x

add :: Int -> Int -> Int
add x y = x + y

greeting :: String -> Int -> String
greeting name age = name ++ " is " ++ show age ++ " years old"

main :: IO ()
main = do
  print (square 7)
  print (add 2 3)
  print (add (square 2) (square 3))
  putStrLn (greeting "Ada" 36)
49
5
13
Ada is 36 years old
  • Arguments are separated by spaces, not commas: add 2 3, not add(2, 3).
  • There's no return: the body is the result.
  • Function application binds tighter than any operator: square 2 + 1 means (square 2) + 1, which is 5.
  • Nested calls need parentheses: add (square 2) (square 3).

Infix and prefix

Any two-argument function can be used between its arguments with backticks, and any operator can be used in front with parentheses:

main :: IO ()
main = do
  print (10 `div` 3)
  print (div 10 3)
  print ((+) 4 5)
  print (3 `max` 9)
3
3
9
9

Defining your own operators

(|>) :: a -> (a -> b) -> b
x |> f = f x

main :: IO ()
main = print (5 |> (* 2) |> show |> length)
2

Operators are just functions whose names are made of symbols. (The standard library already has this one as & in Data.Function.)

Lambdas

An anonymous function is written with a backslash (it looks a bit like the Greek letter λ):

main :: IO ()
main = do
  print ((\x -> x * x) 9)
  print (map (\n -> n * 10) [1, 2, 3])
81
[10,20,30]

Practice

Write hypotenuse :: Double -> Double -> Double using sqrt, and print hypotenuse 3 4.

Show solution
hypotenuse :: Double -> Double -> Double
hypotenuse a b = sqrt (a * a + b * b)

main :: IO ()
main = print (hypotenuse 3 4)
5.0