Exploring Haskell: Defining Functions
Going from conditional expressions and guarded equations to pattern matching, lambda expressions, and operator sections.
As in most programming languages, Haskell supports conditional expression, which also can be used to define a function.
-- Absolute integerabs n = if n >= 0 then n else -n-- Sign of integersignum n = if n < 0 then -1 else if n == 0 then 0 else 1
Guarded equation is a preferred alternative to a conditional expression in Haskell.
-- Absolute integerabs n | n >= 0 = n| otherwise = -n-- Sign of integersignum n | n < 0 = -1| n == 0 = 0| otherwise = 1-- When otherwise is unspecified the default value is otherwise = True
Pattern matching is a simple way to define a function by matching a pattern with an expected result.
-- Boolean negationnot False = Truenot True = False-- Boolean AND (Naive)True && True = TrueTrue && False = FalseFalse && True = FalseFalse && False = False-- Boolean AND (Compact)True && True = True_ && _ = False-- _ is a wildcard to match any symbol-- Boolean AND (Lazy)True && b = bFalse && _ = False
Patterns are matched in order of definition, left to right, top to bottom.
-- Will always return False_ && _ = FalseTrue && True = True
Patterns do not repeating arguments.
-- Conflicting definition of bb && b = b_ && _ = False-- Correct way is to use a guarded equationb && c | b == c = b| otherwise = False
Internally, every non-empty list is constructed by repeated use of an operator
: called cons that adds an element to the start of a list.
[1, 2, 3, 4]-- is actually1:(2:(3:(4:)))
Function on a list can be defined using a
-- Return the first element of a given listhead (x : _) = x-- Return given list without the first elementtail (_ : xs) = xs
x:xscan only match non-empty lists.
x:xspattern must be inside parenthesis because of the order of operations.
A function can be constructed without naming the function by using a lambda expression.
λx -> x + x.
λ is the Greek letter lambda and in Haskell is denoted with a
Usage of Lambda Expressions
Give formal meaning to a curried function.
-- Without lambda expressionadd x y = x + y-- With lambda expressionadd = \x -> (\y -> x + y)
Define a function that returns another function as a result.
-- Without lambda expressionconst x _ = x-- With lambda expressionconst x = \_ -> x
Avoid naming a function that is used once.
-- Without lambda expressionodds n = map f [0 .. n - 1] where f x = x * 2 + 1-- With lambda expressionodds n = map (\x -> x * 2 + 1) [0 .. n - 1]
An operator written between its two arguments can be converted into a curried function written before its two arguments by using parenthesis.
1 + 2 -- 3(+) 1 2 -- 3(1+) 2 -- 3(+2) 1 -- 3
In general if
+ is an operator then functions of the form
(+y) are called sections.
Sections can be used to instead of functions:
(+)is the addition function
\x -> (\y -> x + y)
(1+)is the successor function
\y -> 1 + y
(1/)is the reciprocation function
\y -> 1 / y
(*2)is the doubling function
\x -> x * 2
(/2)is the halving function
\x -> x / 2
And that’s that.