Functional Programming in Haskell
description
Transcript of Functional Programming in Haskell
![Page 1: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/1.jpg)
Functional Programming in
Haskell
Motivation through Concrete Examples
Adapted from Lectures by
Simon Thompson
![Page 2: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/2.jpg)
CS7120 (Prasad) L5-Haskell 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](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/3.jpg)
CS7120 (Prasad) L5-Haskell 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](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/4.jpg)
CS7120 (Prasad) L5-Haskell 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](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/5.jpg)
CS7120 (Prasad) L5-Haskell 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](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/6.jpg)
CS7120 (Prasad) L5-Haskell 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](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/7.jpg)
CS7120 (Prasad) L5-Haskell 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](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/8.jpg)
CS7120 (Prasad) L5-Haskell 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](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/9.jpg)
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.
CS7120 (Prasad) L5-Haskell 9
![Page 10: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/10.jpg)
CS7120 (Prasad) L5-Haskell 11
How many pieces with n cuts?
![Page 11: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/11.jpg)
CS7120 (Prasad) L5-Haskell 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 12: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/12.jpg)
CS7120 (Prasad) L5-Haskell 13
The Pictures case study.
Using a powerful library of functions over lists.
• Pattern matching
• Recursion
• Generic functions
• Higher-order functions
• …
![Page 13: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/13.jpg)
CS7120 (Prasad) L5-Haskell 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 14: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/14.jpg)
CS7120 (Prasad) L5-Haskell 15
Functions over pictures
A function to flip a picture in a vertical mirror:
input outputflipV
![Page 15: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/15.jpg)
CS7120 (Prasad) L5-Haskell 16
Functions over pictures
A function to invert the colours in a picture:
invertColour
![Page 16: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/16.jpg)
CS7120 (Prasad) L5-Haskell 17
Functions over pictures
A function to superimpose two pictures:
superimpose
![Page 17: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/17.jpg)
CS7120 (Prasad) L5-Haskell 18
Functions over pictures
A function to put one picture above another:
above
![Page 18: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/18.jpg)
CS7120 (Prasad) L5-Haskell 19
Functions over pictures
A function to put two pictures side by side:
sideBySide
![Page 19: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/19.jpg)
CS7120 (Prasad) L5-Haskell 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 20: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/20.jpg)
CS7120 (Prasad) L5-Haskell 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 21: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/21.jpg)
CS7120 (Prasad) L5-Haskell 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 22: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/22.jpg)
CS7120 (Prasad) L5-Haskell 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 23: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/23.jpg)
CS7120 (Prasad) L5-Haskell 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 24: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/24.jpg)
CS7120 (Prasad) L5-Haskell 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 25: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/25.jpg)
CS7120 (Prasad) L5-Haskell 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 26: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/26.jpg)
CS7120 (Prasad) L5-Haskell 27
Partial application in Pictures
flipV = map reverse
invertColour = map (map invertChar)
A function[Char]->[Char]
A function[[Char]]->[[Char]]
![Page 27: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/27.jpg)
CS7120 (Prasad) L5-Haskell 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 28: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/28.jpg)
CS7120 (Prasad) L5-Haskell 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 29: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/29.jpg)
CS7120 (Prasad) L5-Haskell 30
Parsing
"((2+3)-4)"
is a sequence of symbols, but underlying it is a structure ...
-
4
2 3
+
![Page 30: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/30.jpg)
CS7120 (Prasad) L5-Haskell 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 31: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/31.jpg)
CS7120 (Prasad) L5-Haskell 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 32: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/32.jpg)
CS7120 (Prasad) L5-Haskell 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 33: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/33.jpg)
CS7120 (Prasad) L5-Haskell 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 34: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/34.jpg)
CS7120 (Prasad) L5-Haskell 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 35: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/35.jpg)
CS7120 (Prasad) L5-Haskell 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 36: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/36.jpg)
CS7120 (Prasad) L5-Haskell 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 37: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/37.jpg)
CS7120 (Prasad) L5-Haskell 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 38: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/38.jpg)
CS7120 (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]L5-Haskell
![Page 39: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/39.jpg)
CS7120 (Prasad) L5-Haskell 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 40: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/40.jpg)
CS7120 (Prasad) L5-Haskell 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 41: Functional Programming in Haskell](https://reader033.fdocuments.us/reader033/viewer/2022061517/56813c6c550346895da5fdac/html5/thumbnails/41.jpg)
CS7120 (Prasad) L5-Haskell 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.
take 100 primes