Transcript
Page 1: HASKELL PROGRAMMING AND FUNCTIONALstever/Haskell_notes.pdf · Functional Programming and Haskell ÐStevedReeves Ð2006 ÐUniversity ofeWaikato 1 FUNCTIONAL PROGRAMMING AND HASKELL

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 1

FUNCTIONAL

PROGRAMMING AND

HASKELL

SOME ELEMENTARY NOTES

Steve Reeves Department of Computer Science

University of Waikato

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 2

Many of these notes are based on

“Haskell: The Craft of Functional Programming”, Simon Thompson, Addison-Wesley, 1996

This introduction is based on chapter one of:

“Functional Programming with Miranda”, Ian Holyer, UCL Press, 1993 which is in the Library.

Other good books, all in the Library, on functional programming are:

“Miranda: The Craft of Functional Programming”, Simon Thompson, Addison-Wesley, 1995 “Introduction to Functional Programming”, Richard Bird and Philip Wadler, Prentice-Hall, 1988

“Elements of Functional Programming”, Chris Reade, Addison-Wesley, 1989

Page 2: HASKELL PROGRAMMING AND FUNCTIONALstever/Haskell_notes.pdf · Functional Programming and Haskell ÐStevedReeves Ð2006 ÐUniversity ofeWaikato 1 FUNCTIONAL PROGRAMMING AND HASKELL

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 3

Also, search the Library catalogues for “functional programming” - there are about 12 more books on the subject in our Library

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 4

Taxonomy

specification

declarative logical functional languages structured procedural high-level low-level

Page 3: HASKELL PROGRAMMING AND FUNCTIONALstever/Haskell_notes.pdf · Functional Programming and Haskell ÐStevedReeves Ð2006 ÐUniversity ofeWaikato 1 FUNCTIONAL PROGRAMMING AND HASKELL

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 5

Procedural Languages

• developed first in the 1950s

• most languages today are procedural

• two common ideas - instructions executed sequentially - values stored in locations • brought together by defining sequences

of instructions to change the contents of storage - procedures, routines

these languages closely match the

architecture of most of today!s computers

- advantage is efficiency - disadvantage is unnecessary

detail

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 6

Evolution machine code low-level

assembly high-level ForTran, BASIC structured C, Pascal, Modula object-oriented Smalltalk

C++

Page 4: HASKELL PROGRAMMING AND FUNCTIONALstever/Haskell_notes.pdf · Functional Programming and Haskell ÐStevedReeves Ð2006 ÐUniversity ofeWaikato 1 FUNCTIONAL PROGRAMMING AND HASKELL

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 7

Declarative Languages

• origins in the !-calculus of 1930s

• became practical in the 1970s • at a higher-level than any of the

procedural languages • breaks away from the procedural model • allows expression of algorithms in a very

clear and direct way • few unnecessary details • values can be defined and manipulated

directly • no need to worry about how or where

they are stored

• algorithms are given by declaring

relationships between values - no concern about the order used

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 8

• Various sorts of expressions declare

relations between values

• Logic programming languages use

relations • Specification languages use any

mathematical structures you like - they are more general and

expressive than either logic of functional languages

- so expressive that you can write

down relations that are not computable!!

• Functional languages use functions

Page 5: HASKELL PROGRAMMING AND FUNCTIONALstever/Haskell_notes.pdf · Functional Programming and Haskell ÐStevedReeves Ð2006 ÐUniversity ofeWaikato 1 FUNCTIONAL PROGRAMMING AND HASKELL

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 9

Programming with Functions

• Functional programming languages • started in the 1980s (LISP started in the 1950s but is “hybrid”, i.e. combines functional and procedural features) • languages like Miranda, Haskell and Gofer

are all very similar

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 10

Functions for Programming • In a functional language, functions are the

basic building blocks from which programs are constructed

• A program is a function from its inputs to

its output:

inputsprogram

output

• This gives rise to two important

differences between functions and procedures:

• functions have no side effects they can have no effect on the

world outside except to deliver a result value

Page 6: HASKELL PROGRAMMING AND FUNCTIONALstever/Haskell_notes.pdf · Functional Programming and Haskell ÐStevedReeves Ð2006 ÐUniversity ofeWaikato 1 FUNCTIONAL PROGRAMMING AND HASKELL

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 11

• functions have no state they give the same result every

time they are evaluated with the same arguments

• this means that functions form self-contained

units all their connections with the

outside world are explicit they are therefore safe and

convenient building blocks

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 12

• two most common ways of combining functions

pass the results of one to the

arguments of another fourth_power n = square (square n)

pass a function as an argument to

another function

square_list ns = map square ns where map f [x1,x2,x3,...,xn] = [f x1, f x2,...,f xn] so square_list [1,2,3,4] = [1,4,9,16]

Page 7: HASKELL PROGRAMMING AND FUNCTIONALstever/Haskell_notes.pdf · Functional Programming and Haskell ÐStevedReeves Ð2006 ÐUniversity ofeWaikato 1 FUNCTIONAL PROGRAMMING AND HASKELL

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 13

• map is an example of a very useful and common value in functional programming, the higher-order function

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 14

Gofer and Haskell • They are lazy, polymorphic, purely

functional programming languages

• Developed following the Haskell Report • We shall be using HUGS-Haskell User!s

Gofer System-Available, free, for PCs (IBM-style and Macs), Ataris, Amigas, larger Unix machines and others

Page 8: HASKELL PROGRAMMING AND FUNCTIONALstever/Haskell_notes.pdf · Functional Programming and Haskell ÐStevedReeves Ð2006 ÐUniversity ofeWaikato 1 FUNCTIONAL PROGRAMMING AND HASKELL

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 15

Using HUGS • In the labs we will be using HUGS running

under Linux

• To run the interpreter just type hugs • Typing :? will show you commands that can be

used :l <file> will load a file called <file>, which you

can fill with definitions, or a script, using any editor like emacs, vi or textedit (under X)

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 16

• any definitions you load from a file will augment the standard definitions which are always available, so extending the set of expressions that can be evaluated

• any expressions you type at the prompt ?

will be evaluated and their value printed as output:

? 2 + 3 5 ? sum [1..10] 55 ? product [1..6] 720

Page 9: HASKELL PROGRAMMING AND FUNCTIONALstever/Haskell_notes.pdf · Functional Programming and Haskell ÐStevedReeves Ð2006 ÐUniversity ofeWaikato 1 FUNCTIONAL PROGRAMMING AND HASKELL

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 17

Data • Simple data or unstructured data - numbers

42 :: Int i.e. 42 has type Int

3.14159 :: Fractional - operations on numbers (+) :: Int -> Int -> Int (+) 2 3 :: Int (+) 2 3 = 5

more usually written 2 + 3, these forms are equivalent

(*),(-),(/),(^) and many more

- characters ‘a’ :: Char

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 18

‘0’ :: Char ‘\n’ :: Char

- operations ord :: Char -> Int chr :: Int -> Char ord ‘a’ = 97 chr 65 = ‘A’ - Booleans True :: Bool False :: Bool - operations (&&) :: Bool -> Bool -> Bool not :: Bool -> Bool True && True = True

Page 10: HASKELL PROGRAMMING AND FUNCTIONALstever/Haskell_notes.pdf · Functional Programming and Haskell ÐStevedReeves Ð2006 ÐUniversity ofeWaikato 1 FUNCTIONAL PROGRAMMING AND HASKELL

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 19

You can get HUGS to tell you the type of

expressions by typing :t ord for example, which will give the response ord :: Char -> Int

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 20

• Structured Data - Lists given a type t, values of type

[t] are lists whose elements

have type t

[1,2,3,4] :: [Int] [‘a’,’b’,’c’,’d’] :: [Char] [True, True, False] :: [Bool] [[1,2],[1,5],[1],[2,3]] :: [[Int]]

[] :: [Char] [] :: [Int] lists can also be written using

the constructor :

[1,2,3] = 1 : 2 : 3 : []

Page 11: HASKELL PROGRAMMING AND FUNCTIONALstever/Haskell_notes.pdf · Functional Programming and Haskell ÐStevedReeves Ð2006 ÐUniversity ofeWaikato 1 FUNCTIONAL PROGRAMMING AND HASKELL

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 21

= 1 : [2,3] = 1 : 2 :[3] :: [Int]

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 22

- operations length xs returns the number

of elements in the list xs

xs ++ ys returns the list of

elements in xs followed by the

elements in ys

map f xs returns the list

obtained by applying the function f to each of the

elements of the list xs

length [1,2,3,4] = 4 length [‘a’,’b’,’c’] = 3 [1,2] ++ [4,5] = [1,2,4,5] map ord [‘a’,’b’] = [97, 98]

Page 12: HASKELL PROGRAMMING AND FUNCTIONALstever/Haskell_notes.pdf · Functional Programming and Haskell ÐStevedReeves Ð2006 ÐUniversity ofeWaikato 1 FUNCTIONAL PROGRAMMING AND HASKELL

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 23

- special lists [n..m] is the list of integers

from n to m

[3..5] = [3,4,5] The list with values of the form [n,n+k..m]

is the list [n,n+k,n+2k,n+3k..n+dk,m] where

n+dk " m < n + (d+1)k [1,3..11] = [1,3,5,7,9,11] [n..] is the list

[n,n+1,n+2,n+3...]

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 24

i.e. no matter how many times you take away the first element, there is always more list - a sort of “infinite” list on numbers starting from n

Page 13: HASKELL PROGRAMMING AND FUNCTIONALstever/Haskell_notes.pdf · Functional Programming and Haskell ÐStevedReeves Ð2006 ÐUniversity ofeWaikato 1 FUNCTIONAL PROGRAMMING AND HASKELL

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 25

- tuples if t1, t2,..., tn (n#2) are types

then (t1, t2,...,tn) is the type of n-

tuples of the form (x1,x2,...,xn) where x1 has type t1,

x2 has type t2 and so on (1, [2], 3) :: (Int, [Int], Int) (True,1,’a’) :: (Bool, Int, Char)

((1,2),(0,1)) :: ((Int,Int),(Int,Int)) • note that we can make lists and tuples of

any values, including the operations above

[(+),(-),(*)] :: [Int -> Int] (ord,chr) :: (Char -> Int, Int -> Char)

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 26

Functions - consider a collection of definitions square :: Int -> Int square n = n * n fourth_power :: Int -> Int fourth_power n = square(square n) twice ::(Int -> Int) -> Int -> Int

twice f x = f (f x) - in the definition of square

above, n is a formal parameter

whose scope is the whole of the definition

- the scope of square is the

whole collection - functions with no arguments

are constant values

Page 14: HASKELL PROGRAMMING AND FUNCTIONALstever/Haskell_notes.pdf · Functional Programming and Haskell ÐStevedReeves Ð2006 ÐUniversity ofeWaikato 1 FUNCTIONAL PROGRAMMING AND HASKELL

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 27

- types are automatically calculated

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 28

• Cases • another important general way of defining

functions is to consider cases using guards

• going back to factorial again, e could have said

fact :: Int -> Int fact n | n == 0 = 1 | n >= 0 = n * fact (n-1) • here the expressions n == 0 and n >= 0, which must always have type Bool, are

called the guards • to evaluate such a definition we evaluate

the guards in turn until we find one that is True - in that case the corresponding

expression on the right-hand side of the =

sign is the value of the function

Page 15: HASKELL PROGRAMMING AND FUNCTIONALstever/Haskell_notes.pdf · Functional Programming and Haskell ÐStevedReeves Ð2006 ÐUniversity ofeWaikato 1 FUNCTIONAL PROGRAMMING AND HASKELL

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 29

• for example we can define a function max

which given two integers has the maximum of the two as its value

max :: Int -> Int -> Int max x y | x >= y = x | y >= x = y

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 30

Example (from Thompson) Assume we are given a function sales :: Int -> Int which gives the weekly sales from a shop

for weeks numbered 0, 1, 2 etc. The task is to calculate the following: • total sales for the period week 0 to week n • the maximum weekly sale during weeks 0

to n • the week in which the maximum sale took

place • whether there is a week between week 0

and week n in which no sales took place • a week between week 0 and week n in

which no sales took place (if there is such a week)

Consider the first of these.

Page 16: HASKELL PROGRAMMING AND FUNCTIONALstever/Haskell_notes.pdf · Functional Programming and Haskell ÐStevedReeves Ð2006 ÐUniversity ofeWaikato 1 FUNCTIONAL PROGRAMMING AND HASKELL

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 31

The total sales for the period week 0 to

week 2 is given by sales 0 + sales 1 + sales 2

If we want this for every value of n, though we are asking for a function

totalsales :: Int -> Int the total sales up to week 0 are just sales 0 the total sales up to week n where n > 0 are sales 0 + sales 1 + sales 2 +...+ sales(n-1) + sales n

|_______________________| this is just the total sales up to week n-1

i.e. totalsales (n-1)

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 32

So totalsales n = totalsales (n-1) + sales n

Putting the two cases together gives totalsales n | n == 0 = sales 0 | n > 0 = totalsales(n-1) + sales n e.g. if we have sales 0 = 7, sales 1 = 2 and sales

2 = 5 then totalsales 2 = totalsales 1 + sales 2 = totalsales 0 + sales 1 + sales 2

= sales 0 + sales 1 + sales 2 = 7 + sales 1 + sales 2 = 7 + 2 + sales 2 = 9 + sales 2 = 9 + 5 = 14

Page 17: HASKELL PROGRAMMING AND FUNCTIONALstever/Haskell_notes.pdf · Functional Programming and Haskell ÐStevedReeves Ð2006 ÐUniversity ofeWaikato 1 FUNCTIONAL PROGRAMMING AND HASKELL

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 33

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 34

Consider the second problem - finding the maximum weekly sale We want a function maxSales :: Int -> Int where - the maximum sale in the weeks up to

week 0 must be sales 0 - when n>0 the maximum weekly sale can

occur in two places either - in the weeks up to and including

week n-1 or - in week n

The maximum sale for the weeks up to week n-1 is maxSales(n-1) and we need

to compare this with sales n to see

which is the biggest and hence the value of maxSales n

We have maxSales n | n==0 = sales 0

Page 18: HASKELL PROGRAMMING AND FUNCTIONALstever/Haskell_notes.pdf · Functional Programming and Haskell ÐStevedReeves Ð2006 ÐUniversity ofeWaikato 1 FUNCTIONAL PROGRAMMING AND HASKELL

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 35

| maxSales(n-1) >= sales n = maxSales(n-1) | otherwise = sales n Recall the function max from page 23

above, then we have the much nicer definition

maxSales n | n==0 = sales 0 | otherwise = max (maxSales(n-1)) (sales n)

In general there is a standard pattern for

definitions:

1) give a value for the function at 0 this is the base case or starting

value 2) give a value for the function at n by

using the value at n-1 this is the recursive case

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 36

• Patterns in function definitions • patterns provide an elegant and concise

way of defining functions

• the cases which a function has to deal with are often suggested by the form of its arguments - patterns make this very clear

• consider the factorial function fact n = n! = 1 * 2 * 3 * ... * n and fact 0 = 1 • In Haskell, one way of writing this is fact :: Int -> Int fact 0 = 1 fact (n+1) = (n+1) * fact n • Given the expression fact 4 to evaluate

we use pattern matching to decide which equation in the definition to use

Page 19: HASKELL PROGRAMMING AND FUNCTIONALstever/Haskell_notes.pdf · Functional Programming and Haskell ÐStevedReeves Ð2006 ÐUniversity ofeWaikato 1 FUNCTIONAL PROGRAMMING AND HASKELL

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 37

• Clearly, fact 4 does not match fact 0

since 4 and 0 cannot be made the same

• However, fact 4 can match fact (n+1) since if we substitute 3 for n, and

we consider 4 to be 3 + 1, the

expressions look the same, i.e. fact (3+1)

• This means that we select the second

equation and so the evaluation for fact 4 proceeds by one step

fact 4 = (3 + 1) * fact 3 • Again, we find one of the equations that

matches fact 3 - considering fact 3 as

fact (2+1) means that the second

equation again matches so we have fact 4 = (3 + 1) * fact 3 = (3 + 1) * (2 + 1) * fact 2

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 38

we do this twice more to get fact 4 =(3 + 1) * fact 3 =(3 + 1) * (2 + 1) * fact 2 =(3 + 1) * (2 + 1) * (1 + 1) * fact 1 =(3 + 1) * (2 + 1) * (1 + 1) * (1 + 0) * fact 0 and now, to evaluate fact 0, we use the

first equation, so finally we have fact 4 =(3 + 1) * fact 3 =(3 + 1) * (2 + 1) * fact 2 =(3 + 1) * (2 + 1) * (1 + 1) * fact 1 =(3 + 1) * (2 + 1) * (1 + 1) * (1 + 0) * fact 0 =(3 + 1) * (2 + 1) * (1 + 1) * (1 + 0) * 1

Page 20: HASKELL PROGRAMMING AND FUNCTIONALstever/Haskell_notes.pdf · Functional Programming and Haskell ÐStevedReeves Ð2006 ÐUniversity ofeWaikato 1 FUNCTIONAL PROGRAMMING AND HASKELL

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 39

which with some simple arithmetic gives 24

as the final value • In general, a pattern is an expression,

perhaps containing some variables, which may be made to match some other expression by some substitution of the variables by some other expressions

• So, 4 and 0 can never match because no

substitution of variables in 4 (there are

none) for any expression can make 4 the

same as 0

• Further, 4 and n+1 can match because 4

can be thought of as 3+1 and 3+1 and n+1

can match because substituting 3 for n

makes the expressions the same

• This idea of function evaluation by pattern matching is very expressive

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 40

• Consider lists - the list [1,2,3,4],

remember, can be written 1 : [2,3,4]

we can define len as

len :: [a] -> Int len [] = 0 len (x:xs) = 1 + len xs • Now evaluate len [1,2,3,4]

len [1,2,3,4] = 1 + len [2,3,4] = 1 + 1 + len [3,4] = 1 + 1 + 1 + len [4] = 1 + 1 + 1 + 1 + len [] = 1 + 1 + 1 + 1 + 0 • So, the list pattern [] matches only []

and the pattern x:xs matches so that x is

Page 21: HASKELL PROGRAMMING AND FUNCTIONALstever/Haskell_notes.pdf · Functional Programming and Haskell ÐStevedReeves Ð2006 ÐUniversity ofeWaikato 1 FUNCTIONAL PROGRAMMING AND HASKELL

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 41

substituted for by the first item in the list and xs is substituted for by the rest of the

list

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 42

• There are pre-defined functions head :: [a] -> a head (x:xs) = x tail :: [a] -> [a] tail (x:xs) = xs

• What are the values of head [1] tail [1] head [] tail [] head ones head (tail ones) head (tail (tail ones) assuming ones = 1 : ones

Page 22: HASKELL PROGRAMMING AND FUNCTIONALstever/Haskell_notes.pdf · Functional Programming and Haskell ÐStevedReeves Ð2006 ÐUniversity ofeWaikato 1 FUNCTIONAL PROGRAMMING AND HASKELL

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 43

User-defined data • So far we have looked at data from types

which are already given in the basic language - now we take a first look at how

users of Haskell can define their own types

We can introduce new types by

declarations like data Day = Sun | Mon | Tues | Weds| Thurs | Fri | Sat

and then we can use pattern-matching to

define functions that work on this new type Day

daybefore Sun = Sat daybefore Sat = Fri daybefore Fri = Thurs daybefore Thurs = Weds daybefore Weds = Tues daybefore Tues = Mon daybefore Mon = Sun

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 44

Strings and Layout Strings are just lists whose elements have

type Char, so strings as types are just [Char]

Examples are [‘a’,’b’] [] [‘ ‘]

There is an abbreviated way of writing strings, so the above become

“ab” ““ “ “ Then we also have that

“ab” ++ “cde”

(which is [‘a’,’b’] ++ [‘c’,’d’,’e’])

Page 23: HASKELL PROGRAMMING AND FUNCTIONALstever/Haskell_notes.pdf · Functional Programming and Haskell ÐStevedReeves Ð2006 ÐUniversity ofeWaikato 1 FUNCTIONAL PROGRAMMING AND HASKELL

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 45

has value “abcde”

(which is [‘a’,’b’,’c’,’d’,’e’])

Note that when the interpreter evaluates strings it leaves the double-quotes off when it prints the value - this aids readability and allows for a natural treatment of the special characters like ‘\n’

For example typing “ab\ncde” to the

interpreter gives the value ab cde :: [Char] The prelude-defined function show :: Int -> [Char] takes an integer n as argument and returns

its usual text representation, as a string, as result

e.g. show 6 = “6” :: [Char]

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 46

Since functions can, of course, have strings as output we can define functions which format output to enhance readability. For example

ints_to :: Int -> [Char] ints_to n = “The numbers from 0 to “ ++ show n ++ “ are\n” ++ ints n

ints 0 = show 0 ints (n+1) = ints n ++ “\n” ++ show (n+1) Then we have ints_to 6 giving the value The numbers from 0 to 6 are 0 1 2 3 4 5

Page 24: HASKELL PROGRAMMING AND FUNCTIONALstever/Haskell_notes.pdf · Functional Programming and Haskell ÐStevedReeves Ð2006 ÐUniversity ofeWaikato 1 FUNCTIONAL PROGRAMMING AND HASKELL

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 47

6

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 48

Back to Lists • develop a function for taking a list of

integers and computing their sum sumlist :: [Int] -> Int • What possible “shapes” of list are there

that we need to consider? • As always, [] and (x:xs) - so two cases

sumlist [] = sumlist (x:xs) = • What about a function to form the product

of all the elements of a list of integers? • What “shapes” do we have to consider?

• What cases, then?

Page 25: HASKELL PROGRAMMING AND FUNCTIONALstever/Haskell_notes.pdf · Functional Programming and Haskell ÐStevedReeves Ð2006 ÐUniversity ofeWaikato 1 FUNCTIONAL PROGRAMMING AND HASKELL

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 49

• Same for a function to take a list of lists and form the list found by concatenating them altogether.

• Notice the pattern with the definitions of

sumlist, prodlist and concat

sumlist [1,2,3] = 1 + 2 + 3 + 0 prodlist [1,2,3] = 1 * 2 * 3 * 1 concat [[1],[2,3],[4,5]] = [1] ++ [2,3] ++ [4,5] ++ [] • In general

f [1,2,3] = 1 f (2 f (3 f c)) where f is some binary function and c is

some starting value - 0 for sumlist, 1 for

prodlist and [] for concat

• We can abstract this pattern and turn it

into a function

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 50

• The pattern is called “folding” the list and since we are grouping from the right-hand end it is called “folding from the right” or, for short, foldr

• Since we have a list as the argument

there are two cases • We also need to say what f and c are

foldr f c [] = c

as in sumlist [] = 0 prodlist [] = 1 concat [] = []

• Then in the general case we have sumlist (x:xs) = x + sumlist xs =(+) x (sumlist xs) prodlist (x:xs) = x * prodlist xs =(*) x (prodlist xs)

Page 26: HASKELL PROGRAMMING AND FUNCTIONALstever/Haskell_notes.pdf · Functional Programming and Haskell ÐStevedReeves Ð2006 ÐUniversity ofeWaikato 1 FUNCTIONAL PROGRAMMING AND HASKELL

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 51

concat (x:xs) = x ++ concat xs =(++) x (concat xs) so we have foldr f c (x:xs) = f x (foldr f c xs) • This search for abstraction is an

important one because we discover patterns in our programming that makes it easier to read, easier to get right and allows for re-use

• Note that sumlist = foldr (+) 0 prodlist = foldr (*) 1 concat = foldr (++) []

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 52

• Zipping • this is another useful operation • it “zips” together two lists, as suggested

by the picture

(1,'a') (2,'b') (3,'c') ( , )4

'd'

5 6 7 8 ...

'e' 'f' 'g' 'h' ...

which is zipping together the two lists [1,2,3,4,5,6,7,8,...] and [‘a’,’b’,’c’,’d’,’e’, ’f’,’g’,’h’,...] we define zip as

zip :: [a] -> [b] -> [(a,b)]

Page 27: HASKELL PROGRAMMING AND FUNCTIONALstever/Haskell_notes.pdf · Functional Programming and Haskell ÐStevedReeves Ð2006 ÐUniversity ofeWaikato 1 FUNCTIONAL PROGRAMMING AND HASKELL

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 53

zip [] ys = [] zip xs [] = [] zip (x:xs)(y:ys)=(x,y):(zip xs ys) examples would be zip [0..] “hello there!” which has value [(0,’h’),(1,’e’),(2,’l’),(3,’l’), (4,’o’),(5,’‘),(6,’t’),(7,’h’), (8,’e’),(9,’r’),(10,’e’),(11,’!’)] (note that when one list finishes then so

does the zipped list)

zip [0..] [0..] which has value [(0,0), (1,1), (2,2), (3,3)...]

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 54

• A further way of putting together lists is by list comprehension

• A list comprehension has the form [ expression | qualifiers ]

• Here expression can be any Haskell

expression • There are several sorts of qualifiers : - generators these are of the form pat <- exp where exp is some expression with a

list type, i.e. type [a] for some a

pat is some pattern the generator extracts each element of

exp that matches pat

Page 28: HASKELL PROGRAMMING AND FUNCTIONALstever/Haskell_notes.pdf · Functional Programming and Haskell ÐStevedReeves Ð2006 ÐUniversity ofeWaikato 1 FUNCTIONAL PROGRAMMING AND HASKELL

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 55

For example [ x*x | x <- [1..5]] has value [1, 4, 9, 16, 25] Note that variables in the pattern can

be used in the expression

- filters this is an expression of type Bool

it is used in conjunction with

generators to filter out unwanted items

as they are generated, as we will see • we can combine qualifiers by writing

them with commas between them • when they are combined in this way

earlier qualifiers in the list pass their values on to later ones

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 56

Page 29: HASKELL PROGRAMMING AND FUNCTIONALstever/Haskell_notes.pdf · Functional Programming and Haskell ÐStevedReeves Ð2006 ÐUniversity ofeWaikato 1 FUNCTIONAL PROGRAMMING AND HASKELL

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 57

• Examples [(x,y) | x <- [1..3], y <- [1..x]] is the list [(1,1),(2,1),(2,2),(3,1) ,(3,2),(3,3)] [x | x <- [1..10], even x] is the list [2, 4, 6, 8, 10] • note that the variables introduced by the

patterns need not be used • this is useful to produce a list of a given

length with each element being the same [ 2 | x <- [1..10]] is the list

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 58

[2,2,2,2,2,2,2,2,2,2] • we can get the list of all squares of

natural numbers squares :: [Int] squares = [x * x | x <- [0..]]

• we can get the list of all prime numbers first some preparation factors :: Int -> [Int] factors n = [x|x<-[1..n], n `mod` x == 0] so factors 5 = [1,5] factors 10 = [1, 2, 5, 10] then define prime :: Int -> [Int] prime n = factors n == [1,n] so prime 5 = True

Page 30: HASKELL PROGRAMMING AND FUNCTIONALstever/Haskell_notes.pdf · Functional Programming and Haskell ÐStevedReeves Ð2006 ÐUniversity ofeWaikato 1 FUNCTIONAL PROGRAMMING AND HASKELL

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 59

prime 10 = False

then primes = [x| x <- [1..], prime x]

• Consider quicksorting take a list, take its first element, divide the

remainder of the list into two lists: one containing those elements less that the chosen one; the other containing those elements not less than the chosen one, sort these two lists then concatenate the two lists either side of the chosen element (yuk!)

qs :: [a] -> [a] qs [] = [] qs (x:xs) = qs[u| u<-xs, u < x] ++ [x] ++

Functional Programming and Haskell–Steve Reeves–2006–University of Waikato 60

qs [u| u<-xs, u >= x] Ah!!


Top Related