functional programming in haskell motivation through concrete examples adapted from lectures by...

42
Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Upload: phoebe-lyons

Post on 28-Dec-2015

221 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Functional Programming in

Haskell

Motivation through Concrete Examples

Adapted from Lectures by

Simon Thompson

Page 2: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 2

Functional Programming

Given the functionsabove invertColour flipH

sideBySide superimpose flipV

and the horse picture, how do you get …

(expression and evaluation)

Page 3: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 3

Definitions in Haskell

name :: Type

name = expression

blackHorse :: Picture

blackHorse = invertColour horse

rotate :: Picture -> Picture

rotate pic = flipH (flipV pic)

Page 4: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 4

Higher-level

Evaluation is about expressions and values, not storage locations.

• No need to allocate/deallocate storage: garbage collection.

• Values don't change over program execution: contrast x=x+1 etc. of Java, C, …

•… instead we describe relations between values by means of (fixed) functions.

Page 5: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 5

Declarative … proofs possible

Programs describe themselves: square n = n*n double n = 2*n

'The square of n is n*n, for every integer n.'

Programs are equations.So we can write proofs using the definitions.

square (double n)

= square (2*n)

= (2*n)*(2*n) = 2*2*n*n

= double (double (square n))

Page 6: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 6

Evaluation freedom

Evaluation can occur in any order ...

(4-3)+(2-1) (4-3)+(2-1) (4-3)+(2-1)

(4-3)+1 1+(2-1) 1+1

1+1 1+1 2

2 2

… and can choose to evaluate only what is needed, when it is needed: lazy evaluation (more later).

Can also evaluate in parallel … efficiently?

Page 7: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 7

History

First 'functional' language, LISP, defined c. 1960 … popular in AI in 70s/80s.

• Now represented best by Scheme.

• Weakly typed; allows side-effects and eval.

Next generation: ML (1980…), Miranda (1985…) and Haskell (1990…).

• Strongly-typed; ML allows references and thus side-effects.

• Miranda and Haskell: pure and lazy.

• FP (1982): heroic experiment by Backus (FORTRAN, ALGOL).

Page 8: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 8

Haskell and Hugs

Named after Haskell Brooks Curry: mathematician and logician; inventor of the -calculus.

Haskell 98 is the recent 'standard' version of Haskell.

Various implementations: Hugs (interpreter for Windows, Mac, Unix) and GHC, NHC, HBC (compilers).

http://www.haskell.org/

Page 9: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Basics: guards and base types

How many of three integers are equal … ?

howManyEqual :: Int -> Int -> Int -> Int

howManyEqual n m k

| n==m && m==k = 3

| n==m || m==k || k==n = 2

| otherwise = 1

If we reach herethey're not all equal …

… and if we reach herethey're all different.

Page 10: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 10

Regular and literate scripts

In a regular script there are definitions and comments:

-- FirstScript.hs

-- 5 October 2000

-- Double an integer.

double :: Int -> Int

double n = 2*n

Everything is program, except comments beginning --.

In a literate script there are comments and definitions:

FirstLit.lhs

5 October 2000

Double an integer.

> double :: Int -> Int

> double n = 2*n

Everything is comment, except program beginning > .

Page 11: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 11

How many pieces with n cuts?

Page 12: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 12

How many pieces with n cuts?

No cuts: 1 piece.

With the nth cut, you get n more pieces:

cuts :: Int -> Int

cuts n

| n==0 = 1

| n>0 = cuts (n-1) + n

| otherwise = 0

Page 13: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 13

The Pictures case study.

Using a powerful library of functions over lists.

• Pattern matching

• Recursion

• Generic functions

• Higher-order functions

• …

Page 14: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 14

Using Hugs

expr Evaluate expr

:type expr Give the type of expr

:l Blah Load the file Blah.hs

:r Reload the last file

:? Help: list commands

:e Edit the current file

:q Quit

Page 15: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 15

Functions over pictures

A function to flip a picture in a vertical mirror:

input outputflipV

Page 16: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 16

Functions over pictures

A function to invert the colours in a picture:

invertColour

Page 17: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 17

Functions over pictures

A function to superimpose two pictures:

superimpose

Page 18: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 18

Functions over pictures

A function to put one picture above another:

above

Page 19: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 19

Functions over pictures

A function to put two pictures side by side:

sideBySide

Page 20: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 20

A naïve implementation

type Picture = [String]

type String = [Char]

A Picture is a list of Strings.A String is a list of Char (acters).

.......##...

.....##..#..

...##.....#.

..#.......#.

..#...#...#.

..#...###.#.

.#....#..##.

..#...#.....

...#...#....

....#..#....

.....#.#....

......##....

Page 21: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 21

How are they implemented?

flipH Reverse the list of strings.

flipV Reverse each string.

rotate flipH then flipV (or v.versa).

above Join the two lists of strings.

sideBySide Join corresponding lines.

invertColour Change each Char … and each

line.

superimpose Join each Char … join each line.

Page 22: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 22

How are they implemented?

flipH reverse

flipV map reverse

rotate flipV . flipH

above ++

sideBySide zipWith (++)

invertColour map (map invertChar)

superimpose zipWith (zipWith combine)

Page 23: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 23

Lists and types

Haskell is strongly typed: detect all type errors before evaluation.

For each type t there is a type [t], 'list of t'.

reverse [] = []

reverse (x:xs) = reverse xs ++ [x]

reverse :: [a] -> [a]

a is a type variable: reverse works over any list type, returning a list of the same type.

Page 24: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 24

Flipping in a vertical mirror

flipV :: Picture -> Picture

flipV [] = []

flipV (x:xs) = reverse x : flipV xs

Run along the list, applying reverse to each element

Run along the list, applying … to every element.

General pattern of computation.

Page 25: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 25

Implementing the mapping pattern

map f [] = []

map f (x:xs) = f x : map f xs

map :: (a -> b) -> [a] -> [b]

Examples over pictures:

flipV pic = map reverse pic

invertColour pic = map invertLine pic

invertLine line = map invertChar line

Page 26: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 26

Functions as data

Haskell allows you to pass functions as arguments and return functions as results, put them into lists, etc. In contrast, in Pascal and C, you can only pass named functions, not functions you build dynamically.

map isEven = ??

map isEven :: [Int] -> [Bool]

It is a partial application, which gives a function:give it a [Int] and it will give you back a [Bool]

Page 27: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 27

Partial application in Pictures

flipV = map reverse

invertColour = map (map invertChar)

A function[Char]->[Char]

A function[[Char]]->[[Char]]

Page 28: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 28

Another pattern: zipping together

sideBySide [l1,l2,l3] [r1,r2,r3]

= [ l1++r1, l2++r2, l3++r3 ]

zipWith :: (a->b->c) -> [a] -> [b] -> [c]

zipWith f (x:xs) (y:ys)

= f x y : zipWith f xs ys

zipWith f xs ys = []

Page 29: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 29

In the case study …

sideBySide = zipWith (++)

Superimposing two pictures: need to combine individual elements:

combine :: Char -> Char -> Char

combine top btm

= if (top=='.' && btm=='.') then '.' else '#'

superimpose = zipWith (zipWith combine)

Page 30: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 30

Parsing

"((2+3)-4)"

is a sequence of symbols, but underlying it is a structure ...

-

4

2 3

+

Page 31: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 31

Arithmetical expressions

An expression is either

• a literal, such as 234 or a composite expression:

• the sum of two expressions (e1+e2)

• the difference of two expressions (e1-e2)

• the product of two expressions (e1*e2)

Page 32: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 32

How to represent these structures?

data Expr = Lit Int |

Sum Expr Expr |

Minus Expr Expr |

Times Expr Expr

Elements of this algebraic data type include

Lit 34 34

Sum (Lit 45) (Lit 3) (45+3)

Minus (Sum (Lit 2) (Lit 3)) (Lit 4) ((2+3)-4)

Page 33: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 33

Counting operators

data Expr = Lit Int | Sum Expr Expr | Minus ...

How many operators in an expression?

Definition using pattern matching

cOps (Lit n) = 0

cOps (Sum e1 e2) = cOps e1 + cOps e2 + 1

cOps (Minus e1 e2) = cOps e1 + cOps e2 + 1

cOps (Times e1 e2) = cOps e1 + cOps e2 + 1

Page 34: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 34

Evaluating expressions

data Expr = Lit Int | Sum Expr Expr | Minus ...

Literals are themselves …

eval (Lit n) = n

… in other cases, evaluate the two arguments and then combine the results …

eval (Sum e1 e2) = eval e1 + eval e2

eval (Minus e1 e2) = eval e1 - eval e2

eval (Times e1 e2) = eval e1 * eval e2

Page 35: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 35

List comprehensions

Example list x = [4,3,2,5][ n+2 | n<-x, isEven n]

run through the n in x …4 3 2 5

select those which are even …4 2

and add 2 to each of them6 4

giving the result[6,4]

Page 36: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 36

List comprehensions

Example lists x = [4,3,2] y = [12,17][ n+m | n<-x, m<-y]

run through the n in x …4 3 2

and for each, run through the m in y …12 17 12 17 12 17

add corresponding pairs16 21 15 20 14 19

giving the result[16,21,15,20,14,19]

Page 37: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 37

Quicksort

qsort [] = []

qsort (x:xs) =

qsort elts_lt_x

++ [x]

++ qsort elts_greq_x

where

elts_lt_x = [y | y <- xs, y < x]

elts_greq_x = [y | y <- xs, y >= x]

Page 38: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 38

MergeSort

mergeSort [] = []

mergeSort [x] = [x]

mergeSort xs | size >= 1 =

merge (mergeSort front) (mergeSort back)

where size = length xs `div` 2

front = take size xs

back = drop size xs

Page 39: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad 39

Merging

x

y

x <= y?

merge [1, 3] [2, 4] 1 : merge [3] [2, 4]

1 : 2 : merge [3] [4]

1 : 2 : 3 : merge [] [4]

1 : 2 : 3 : [4] [1,2,3,4]

Page 40: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 40

Defining Merge

merge (x : xs) (y : ys)

| x <= y = x : merge xs (y : ys)

| x > y = y : merge (x : xs) ys

merge [] ys = ys

merge xs [] = xs

One list getssmaller.

Two possiblebase cases.

Page 41: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 41

Lazy evaluation

Only evaluate what is needed … infinite lists

nums :: Int -> [Int]

nums n = n : nums (n+1)

sft (x:y:zs) = x+y

sft (nums 3)

= sft (3: nums 4)

= sft (3: 4: nums 5)

= 7

Page 42: Functional Programming in Haskell Motivation through Concrete Examples Adapted from Lectures by Simon Thompson

Prasad CS776 42

The list of prime numbers

primes = sieve (nums 2)

sieve (x:xs)

= x : sieve [ z | z<-xs, z `mod` x /= 0]

To sieve (x:xs) return x, together with the result of sieveing xs with all multiples of x removed.