62
1 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

Embed Size (px)

DESCRIPTION

Example Summing the integers 1 to 10 in Java: total = 0; for (i = 1; i  10; ++i) total = total+i; The computation method is variable assignment. 2

Citation preview

Page 1: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

1

INTRODUCTION TOFUNCTIONAL PROGRAMMING

Graham HuttonUniversity of Nottingham

Page 2: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

2

What is Functional Programming?

Functional programming is style of programming in which the basic method of computation is the application of functions to arguments;

A functional language is one that supports and encourages the functional style.

Opinions differ, and it is difficult to give a precise definition, but generally speaking:

Page 3: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

Example

Summing the integers 1 to 10 in Java:

total = 0;for (i = 1; i 10; ++i) total = total+i;

The computation method is variable assignment.

3

Page 4: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

Example

Summing the integers 1 to 10 in Haskell:

sum [1..10]

The computation method is function application.

4

Page 5: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

5

Why is it Useful?

Again, there are many possible answers to this question, but generally speaking:

The abstract nature of functional programming leads to considerably simpler programs;

It also supports a number of powerful new ways to structure and reason about programs.

Page 6: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

6

This Course

A series of mini-lectures (with exercises) reviewing a number of basic concepts, using Haskell:The Hugs system;Types and classes I/II;Defining functions;List comprehensions;Recursive functions;Higher-order functions;Functional parsers;Defining types.

Page 7: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

7

These concepts will be tied together at the end by two extended programming examples, concerning a simple game and a simple compiler.

Note:

The material in this course is based upon my forthcoming book, Programming in Haskell;

Please ask questions during the lectures!

Page 8: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

8

LECTURE 1THE HUGS SYSTEM

Graham HuttonUniversity of Nottingham

Page 9: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

9

What is Hugs?An interpreter for Haskell, and the most

widely used implementation of the language;

An interactive system, which is well-suited for teaching and prototyping purposes;

Hugs is freely available from:www.haskell.org/hugs

Page 10: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

10

The Standard Prelude

When Hugs is started it first loads the library file Prelude.hs, and then repeatedly prompts the user for an expression to be evaluated.

For example:

> 2+3*414

> (2+3)*420

Page 11: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

11

> length [1,2,3,4]4

> product [1,2,3,4]24

> take 3 [1,2,3,4,5][1,2,3]

The standard prelude also provides many useful functions that operate on lists. For example:

Page 12: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

12

Function Application

In mathematics, function application is denoted using parentheses, and multiplication is often denoted using juxtaposition or space.

f(a,b) + c d

Apply the function f to a and b, and add the result to the product of c

and d.

Page 13: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

13

In Haskell, function application is denoted using space, and multiplication is denoted using *.

f a b + c*d

As previously, but in Haskell syntax.

Page 14: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

14

Moreover, function application is assumed to have higher priority than all other operators.

f a + b

Means (f a) + b, rather than f (a + b).

Page 15: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

15

Examples

Mathematics Haskell

f(x)

f(x,y)

f(g(x))

f(x,g(y))

f(x)g(y)

f x

f x y

f (g x)

f x (g y)

f x * g y

Page 16: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

16

My First Script

double x = x + x

quadruple x = double (double x)

When developing a Haskell script, it is useful to keep two windows open, one running an editor for the script, and the other running Hugs.

Start an editor, type in the following two function definitions, and save the script as test.hs:

Page 17: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

17

% hugs test.hs

Leaving the editor open, in another window start up Hugs with the new script:

> quadruple 1040

> take (double 2) [1..6][1,2,3,4]

Now both Prelude.hs and test.hs are loaded, and functions from both scripts can be used:

Page 18: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

18

factorial n = product [1..n]

average ns = sum ns `div` length ns

Leaving Hugs open, return to the editor, add the following two definitions, and resave:

div is enclosed in back quotes, not forward;

x `f` y is just syntactic sugar for f x y.

Note:

Page 19: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

19

> :reloadReading file "test.hs"

> factorial 103628800

> average [1..5]3

Hugs does not automatically reload scripts when they are changed, so a reload command must be executed before the new definitions can be used:

Page 20: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

20

ExercisesTry out some of the other functions from the standard prelude using Hugs.

Work through "My First Script" using Hugs.

Show how the functions last and init from the standard prelude could be re-defined using other functions from the prelude.

Note: there are many possible answers!

(1)

(2)

(3)

Page 21: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

21

LECTURE 2TYPES AND CLASSES (I)

Graham HuttonUniversity of Nottingham

Page 22: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

22

What is a Type?

A type is a collection of related values.

Bool

Bool Bool

The logical valuesFalse and True.

All functions that map a logical

value to a logical value.

Page 23: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

23

Types in Haskell

False :: Bool

not :: Bool Bool

not False :: Bool

False && True :: Bool

We use the notation e :: T to mean that evaluating the expression e will produce a value of type T.

Page 24: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

24

Every expression must have a valid type, which is calculated prior to evaluating the expression by a process called type inference;

Haskell programs are type safe, because type errors can never occur during evaluation;

Type inference detects a very large class of programming errors, and is one of the most powerful and useful features of Haskell.

Note:

Page 25: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

25

Basic TypesHaskell has a number of basic types, including:

Char

String

Integer

Int

Bool - Logical values

- Single characters

- Strings of characters

- Fixed-precision integers

- Arbitrary-precision integers

Page 26: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

26

List Types

[False,True,False] :: [Bool]

[’a’,’b’,’c’,’d’] :: [Char]

In general:

A list is sequence of values of the same type:

[T] is the type of lists with elements of type T.

Page 27: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

27

The type of a list says nothing about its length:

[False,True] :: [Bool]

[False,True,False] :: [Bool]

[[’a’],[’b’,’c’]] :: [[Char]]

Note:

The type of the elements is unrestricted. For example, we can have lists of lists:

Page 28: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

28

Tuple TypesA tuple is a sequence of values of different types:

(False,True) :: (Bool,Bool)

(False,’a’,True) :: (Bool,Char,Bool)

In general:(T1,T2,…,Tn) is the type of n-tuples whose ith components have type Ti for any i in 1…n.

Page 29: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

29

The type of a tuple encodes its arity:

(False,True) :: (Bool,Bool)

(False,True,False) :: (Bool,Bool,Bool)

(’a’,(False,’b’)) :: (Char,(Bool,Char))

(True,[’a’,’b’]) :: (Bool,[Char])

Note:

The type of the components is unrestricted:

Page 30: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

30

Function Types

not :: Bool Bool

isDigit :: Char Bool

In general:

A function is a mapping from values of one type to values of another type:

T1 T2 is the type of functions that map arguments of type T1 to results of type T2.

Page 31: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

31

The argument and result types are unrestricted. For example, functions with multiple arguments or results are possible using lists or tuples:

Note:

add :: (Int,Int) Intadd (x,y) = x+y

zeroto :: Int [Int]zeroto n = [0..n]

Page 32: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

32

Exercises

[’a’,’b’,’c’]

(’a’,’b’,’c’)

[(False,’0’),(True,’1’)]

[isDigit,isLower,isUpper]

What are the types of the following values?(1)

Check your answers using Hugs.(2)

Page 33: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

33

LECTURE 3TYPES AND CLASSES (II)

Graham HuttonUniversity of Nottingham

Page 34: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

34

Functions with multiple arguments are also possible by returning functions as results:

add’ :: Int (Int Int)add’ x y = x+y

add’ takes an integer x and returns a function. In turn, this function takes an integer y and

returns the result x+y.

Curried Functions

Page 35: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

35

add and add’ produce the same final result, but add takes its two arguments at the same time, whereas add’ takes them one at a time:

Note:

Functions that take their arguments one at a time are called curried functions.

add :: (Int,Int) Int

add’ :: Int (Int Int)

Page 36: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

36

Functions with more than two arguments can be curried by returning nested functions:

mult :: Int (Int (Int Int))mult x y z = x*y*z

mult takes an integer x and returns a function, which in turn takes an integer y and returns a function,

which finally takes an integer z and returns the result x*y*z.

Page 37: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

37

Curry Conventions

The arrow associates to the right.

Int Int Int Int

To avoid excess parentheses when using curried functions, two simple conventions are adopted:

Means Int (Int (Int Int)).

Page 38: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

38

As a consequence, it is then natural for function application to associate to the left.

mult x y z

Means ((mult x) y) z.

Unless tupling is explicitly required, all functions in Haskell are normally defined in curried form.

Page 39: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

39

Polymorphic TypesThe function length calculates the length of any list, irrespective of the type of its elements.

> length [1,3,5,7]4

> length ["Yes","No"]2

> length [isDigit,isLower,isUpper]3

Page 40: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

40

This idea is made precise in the type for length by the inclusion of a type variable:

length :: [a] Int

For any type a, length takes a list of values of type a and returns an

integer.

A type with variables is called polymorphic.

Page 41: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

41

Many of the functions defined in the standard prelude are polymorphic. For example:

fst :: (a,b) a head :: [a] a

take :: Int [a] [a]

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

Note:

Page 42: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

42

Overloaded TypesThe arithmetic operator + calculates the sum of any two numbers of the same numeric type.

For example:

> 1+23

> 1.1 + 2.23.3

Page 43: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

43

This idea is made precise in the type for + by the inclusion of a class constraint:

(+) :: Num a a a a

For any type a in the class Num of numeric types, + takes two values of type a

and returns another.

A type with constraints is called overloaded.

Page 44: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

44

Classes in HaskellA class is a collection of types that support certain operations, called the methods of the class.

EqTypes whose values can be compared for

equality and difference using

(==) :: a a Bool(/=) :: a a Bool

Page 45: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

45

Eq - Equality types

Ord - Ordered types

Show - Showable types

Haskell has a number of basic classes, including:

Read - Readable types

Num - Numeric types

Page 46: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

46

(==) :: Eq a a a Bool

(<) :: Ord a a a Bool

show :: Show a a String

read :: Read a String a

() :: Num a a a a

Example methods:

Page 47: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

47

Exercises

second xs = head (tail xs)swap (x,y) = (y,x)pair x y = (x,y)double x = x*2palindrome xs = reverse xs == xstwice f x = f (f x)

What are the types of the following functions?(1)

Check your answers using Hugs.(2)

Page 48: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

48

LECTURE 4DEFINING FUNCTIONS

Graham HuttonUniversity of Nottingham

Page 49: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

49

Conditional ExpressionsAs in most programming languages, functions can be defined using conditional expressions.

abs :: Int Intabs n = if n 0 then n else -n

abs takes an integer n and returns n if it is non-negative and

-n otherwise.

Page 50: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

50

Conditional expressions can be nested:

signum :: Int Intsignum n = if n < 0 then -1 else if n == 0 then 0 else 1

In Haskell, conditional expressions must always have an else branch, which avoids any possible ambiguity problems with nested conditionals.

Note:

Page 51: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

51

Guarded EquationsAs 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.

Page 52: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

52

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

The catch all condition otherwise is defined in the prelude by otherwise = True.

Note:

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

Page 53: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

53

Pattern MatchingMany functions have a particularly clear definition using pattern matching on their arguments.

not :: Bool Boolnot False = Truenot True = False

not maps False to True, and True to False.

Page 54: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

54

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

(&&) :: Bool Bool BoolTrue && True = TrueTrue && False = FalseFalse && True = False False && False = False

True && True = True_ && _ = False

can be defined more compactly by

Page 55: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

55

False && _ = FalseTrue && b = b

However, the following definition is more efficient, as it avoids evaluating the second argument if the first argument is False:

The underscore symbol _ is the wildcard pattern that matches any argument value.

Note:

Page 56: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

56

List PatternsIn Haskell, every non-empty list is constructed by repeated use of an operator : called “cons” that adds a new element to the start of a list.

[1,2,3]

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

Page 57: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

57

The cons operator can also be used in patterns, in which case it destructs a non-empty list.

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

tail :: [a] [a]tail (_:xs) = xs

head and tail map any non-empty list to its first and remaining

elements.

Page 58: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

58

Lambda Expressions

A function can be constructed without giving it a name by using a lambda expression.

x x+1

The nameless function that takes a number x and returns the

result x+1.

Page 59: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

59

Why Are Lambda's Useful?Lambda expressions can be used to give a formal meaning to functions defined using currying.

For example:

add x y = x+y

add = x (y x+y)

means

Page 60: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

60

compose f g x = f (g x)

is more naturally defined by

compose f g = x f (g x)

Lambda expressions are also useful when defining functions that return functions as results.

For example,

Page 61: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

61

Exercises

Assuming that else branches were optional in conditional expressions, give an example of a nested conditional with ambiguous meaning.

(1)

Give three possible definitions for the logical or operator || using pattern matching.

(2)

Page 62: 0 INTRODUCTION TO FUNCTIONAL PROGRAMMING Graham Hutton University of Nottingham

62

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:

(i) a conditional expression; (ii) guarded equations; (iii) pattern matching.

Hint:

The prelude function null :: [a] Bool can be used to test if a list is empty.

(3)