0% found this document useful (0 votes)
56 views

Programming in Haskell: Chapter 4 - Defining Functions

This document discusses different ways to define functions in Haskell, including conditional expressions, guarded equations, pattern matching, lambda expressions, and operator sections. It provides examples of defining the abs, signum, not, and, or, head, tail, and successor functions using these techniques. Key points are that patterns must be exhaustive and match in order, and that sections allow operators to be partially applied as functions.

Uploaded by

Tân Đinh Như
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
56 views

Programming in Haskell: Chapter 4 - Defining Functions

This document discusses different ways to define functions in Haskell, including conditional expressions, guarded equations, pattern matching, lambda expressions, and operator sections. It provides examples of defining the abs, signum, not, and, or, head, tail, and successor functions using these techniques. Key points are that patterns must be exhaustive and match in order, and that sections allow operators to be partially applied as functions.

Uploaded by

Tân Đinh Như
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 21

PROGRAMMING IN HASKELL

Chapter 4 - Defining Functions

1
Conditional Expressions

As in most programming languages, functions can


be defined using conditional expressions.

abs :: Int  Int


abs n = if n ≥ 0 then n else -n

abs takes an integer n and returns n if it


is non-negative and -n otherwise.
2
Conditional expressions can be nested:

signum :: Int  Int


signum n = if n < 0 then -1 else
if n == 0 then 0 else 1

Note:

 In Haskell, conditional expressions must always


have an else branch, which avoids any possible
ambiguity problems with nested conditionals.
3
Guarded Equations

As an alternative to conditionals, functions can also


be defined using guarded equations.

abs n | n ≥ 0 = n
| otherwise = -n

As previously, but using guarded equations.


4
Guarded equations can be used to make definitions
involving multiple conditions easier to read:

signum n | n < 0 = -1
| n == 0 = 0
| otherwise = 1

Note:

 The catch all condition otherwise is defined in


the prelude by otherwise = True.
5
Pattern Matching

Many functions have a particularly clear definition


using pattern matching on their arguments.

not :: Bool  Bool


not False = True
not True = False

not maps False to True, and True to False.


6
Functions can often be defined in many different
ways using pattern matching. For example

(&&) :: Bool  Bool  Bool


True && True = True
True && False = False
False && True = False
False && False = False

can be defined more compactly by

True && True = True


_ && _ = False
7
However, the following definition is more efficient,
because it avoids evaluating the second argument
if the first argument is False:

True && b = b
False && _ = False

Note:

 The underscore symbol _ is a wildcard pattern


that matches any argument value.
8
 Patterns are matched in order. For example, the
following definition always returns False:

_ && _ = False
True && True = True

 Patterns may not repeat variables. For example,


the following definition gives an error:

b && b = b
_ && _ = False
9
List Patterns

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]

Means 1:(2:(3:(4:
[]))).

10
Functions on lists can be defined using x:xs patterns.

head :: [a]  a
head (x:_) = x

tail :: [a]  [a]


tail (_:xs) = xs

head and tail map any non-empty list to


its first and remaining elements.
11
Note:

 x:xs patterns only match non-empty lists:

> head []
*** Exception: empty list

 x:xs patterns must be parenthesised, because


application has priority over (:). For example,
the following definition gives an error:

head x:_ = x
12
Lambda Expressions

Functions can be constructed without naming the


functions by using lambda expressions.

x  x + x

the nameless function that takes a


number x and returns the result x + x.
13
Note:

 The symbol  is the Greek letter lambda, and is


typed at the keyboard as a backslash \.

 In mathematics, nameless functions are usually


denoted using the  symbol, as in x  x + x.

 In Haskell, the use of the  symbol for nameless


functions comes from the lambda calculus, the
theory of functions on which Haskell is based.

14
Why Are Lambda's Useful?

Lambda expressions can be used to give a formal


meaning to functions defined using currying.
For example:

add :: Int  Int  Int


add x y = x + y

means

add :: Int  (Int  Int)


add = x  (y  x + y)
15
Lambda expressions can be used to avoid naming
functions that are only referenced once.

For example:

odds n = map f [0..n-1]


where
f x = x*2 + 1

can be simplified to

odds n = map (x  x*2 + 1) [0..n-1]


16
Operator Sections

An operator written between its two arguments can


be converted into a curried function written before
its two arguments by using parentheses.

For example:

> 1+2
3

> (+) 1 2
3
17
This convention also allows one of the arguments
of the operator to be included in the parentheses.

For example:

> (1+) 2
3

> (+2) 1
3

In general, if  is an operator then functions of the


form (), (x) and (y) are called sections.
18
Why Are Sections Useful?

Useful functions can sometimes be constructed in


a simple way using sections. For example:

(1+) - successor function

(1/) - reciprocation function

(*2) - doubling function

(/2) - halving function


19
Exercises

(1) Consider a function safetail that behaves in the


same way as tail, except that safetail maps the
empty list to the empty list, whereas tail gives
an error in this case. Define safetail using:

(a) a conditional expression;


(b) guarded equations;
(c) pattern matching.

Hint: the library function null :: [a]  Bool can


be used to test if a list is empty.
20
(2) Give three possible definitions for the logical
or operator (||) using pattern matching.

(3) Redefine the following version of (&&) using


conditionals rather than patterns:

True && True = True


_ && _ = False

(4) Do the same for the following version:

True && b = b
False && _ = False
21

You might also like