# Functional Programming in Haskell

Post on 07-Jan-2016

30 views

Embed Size (px)

DESCRIPTION

Functional Programming in Haskell. Motivation through Concrete Examples Adapted from Lectures by Simon Thompson. Functional Programming. Given the functions above invertColour flipH sideBySide superimpose flipV and the horse picture, - PowerPoint PPT PresentationTRANSCRIPT

Functional Programming in Haskell

Motivation through Concrete Examples

Adapted from Lectures bySimon Thompson

L5-Haskell

CS7120 (Prasad)L5-Haskell*Functional Programming Given the functionsabove invertColour flipH sideBySide superimpose flipVand the horse picture, how do you get

(expression and evaluation)

L5-Haskell

CS7120 (Prasad)L5-Haskell*Definitions in Haskellname :: Typename = expression

blackHorse :: PictureblackHorse = invertColour horse

rotate :: Picture -> Picturerotate pic = flipH (flipV pic)

L5-Haskell

CS7120 (Prasad)L5-Haskell*Higher-levelEvaluation 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.

L5-Haskell

CS7120 (Prasad)L5-Haskell*Declarative proofs possiblePrograms 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))

L5-Haskell

CS7120 (Prasad)L5-Haskell*Evaluation freedomEvaluation 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?

L5-Haskell

CS7120 (Prasad)L5-Haskell*HistoryFirst '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).

L5-Haskell

CS7120 (Prasad)L5-Haskell*Haskell and HugsNamed 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/

L5-Haskell

Basics: guards and base typesHow 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 = 1CS7120 (Prasad)L5-Haskell*

L5-Haskell

CS7120 (Prasad)L5-Haskell*Regular and literate scriptsIn a regular script there are definitions and comments:

-- FirstScript.hs-- 5 October 2000

-- Double an integer.

double :: Int -> Intdouble n = 2*n

Everything is program, except comments beginning --. In a literate script there are comments and definitions:

FirstLit.lhs5 October 2000

Double an integer.

> double :: Int -> Int> double n = 2*n

Everything is comment, except program beginning > .

L5-Haskell

CS7120 (Prasad)L5-Haskell*How many pieces with n cuts?

L5-Haskell

CS7120 (Prasad)L5-Haskell*How many pieces with n cuts?No cuts: 1 piece.

With the nth cut, you get n more pieces:

cuts :: Int -> Intcuts n | n==0 = 1 | n>0 = cuts (n-1) + n | otherwise = 0

L5-Haskell

CS7120 (Prasad)L5-Haskell*The Pictures case study.

Using a powerful library of functions over lists. Pattern matching Recursion Generic functions Higher-order functions

L5-Haskell

CS7120 (Prasad)L5-Haskell*Using Hugs

exprEvaluate expr:type exprGive the type of expr:l BlahLoad the file Blah.hs:rReload the last file:?Help: list commands:eEdit the current file:qQuit

L5-Haskell

CS7120 (Prasad)L5-Haskell*Functions over picturesA function to flip a picture in a vertical mirror:flipV

L5-Haskell

CS7120 (Prasad)L5-Haskell*Functions over picturesA function to invert the colours in a picture:

L5-Haskell

CS7120 (Prasad)L5-Haskell*Functions over picturesA function to superimpose two pictures:superimpose

L5-Haskell

CS7120 (Prasad)L5-Haskell*Functions over picturesA function to put one picture above another:above

L5-Haskell

CS7120 (Prasad)L5-Haskell*Functions over picturesA function to put two pictures side by side:sideBySide

L5-Haskell

CS7120 (Prasad)L5-Haskell*A nave implementationtype Picture = [String]type String = [Char]

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

L5-Haskell

CS7120 (Prasad)L5-Haskell*How are they implemented?flipHReverse the list of strings.flipVReverse each string.rotateflipH then flipV (or v.versa).aboveJoin the two lists of strings.sideBySideJoin corresponding lines.invertColourChange each Char and each line.superimposeJoin each Char join each line.

L5-Haskell

CS7120 (Prasad)L5-Haskell*How are they implemented?flipHreverseflipVmap reverserotateflipV . flipH above++sideBySidezipWith (++)invertColourmap (map invertChar)superimposezipWith (zipWith combine)

L5-Haskell

CS7120 (Prasad)L5-Haskell*Lists and typesHaskell 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.

L5-Haskell

CS7120 (Prasad)L5-Haskell*Flipping in a vertical mirrorflipV :: 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.

L5-Haskell

CS7120 (Prasad)L5-Haskell*Implementing the mapping patternmap f [] = []map f (x:xs) = f x : map f xs

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

Examples over pictures:

flipV pic = map reverse picinvertColour pic = map invertLine picinvertLine line = map invertChar line

L5-Haskell

CS7120 (Prasad)L5-Haskell*Functions as dataHaskell 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]

L5-Haskell

CS7120 (Prasad)L5-Haskell*Partial application in PicturesflipV = map reverse

invertColour = map (map invertChar)

L5-Haskell

CS7120 (Prasad)L5-Haskell*Another pattern: zipping togethersideBySide [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 = []

L5-Haskell

CS7120 (Prasad)L5-Haskell*In the case study sideBySide = zipWith (++)

Superimposing two pictures: need to combine individual elements:

combine :: Char -> Char -> Charcombine top btm = if (top=='.' && btm=='.') then '.' else '#'

superimpose = zipWith (zipWith combine)

L5-Haskell

CS7120 (Prasad)L5-Haskell*Parsing "((2+3)-4)"

is a sequence of symbols, but underlying it is a structure ...-423+

L5-Haskell

CS7120 (Prasad)L5-Haskell*Arithmetical expressionsAn 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)

L5-Haskell

CS7120 (Prasad)L5-Haskell*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 3434Sum (Lit 45) (Lit 3)(45+3)Minus (Sum (Lit 2) (Lit 3)) (Lit 4)((2+3)-4)

L5-Haskell

CS7120 (Prasad)L5-Haskell*Counting operatorsdata Expr = Lit Int | Sum Expr Expr | Minus ...

How many operators in an expression?

Definition using pattern matching

cOps (Lit n) = 0cOps (Sum e1 e2) = cOps e1 + cOps e2 + 1cOps (Minus e1 e2) = cOps e1 + cOps e2 + 1cOps (Times e1 e2) = cOps e1 + cOps e2 + 1

L5-Haskell

CS7120 (Prasad)L5-Haskell*Evaluating expressionsdata 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 e2eval (Minus e1 e2) = eval e1 - eval e2eval (Times e1 e2) = eval e1 * eval e2

L5-Haskell

- CS7120 (Prasad)L5-Haskell*List comprehensionsExample list x = [4,3,2,5][ n+2 | n
- CS7120 (Prasad)L5-Haskell* List comprehensionsExample lists x = [4,3,2] y = [12,17][ n+m | n
CS7120 (Prasad)L5-Haskell*Quicksortqsort [] = []qsort (x:xs) = qsort elts_lt_x ++ [x] ++ qsort elts_greq_x

where elts_lt_x = [y | y

CS7120 (Prasad)L5-Haskell*MergeSort mergeSort [] = []mergeSort [x] = [x]mergeSort xs | size > 1 = merge (mergeSort front) (mergeSort back)where size = length xs `div` 2 front = take size xsback = drop size xs

L5-Haskell

- CS7120 (Prasad)*Mergingxyx
CS7120 (Prasad)L5-Haskell*Defining Merge merge (x : xs) (y : ys)| x y= y : merge (x : xs) ysmerge [] ys= ysmerge xs []= xsOne list getssmaller.Two possiblebase cases.

L5-Haskell

CS7120 (Prasad)L5-Haskell* Lazy evaluationOnly 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

L5-Haskell

CS7120 (Prasad)L5-Haskell*The list of prime numbersprimes = sieve (nums 2)

sieve (x:xs) = x : sieve [ z | z [a] -> [a]Can join a list of lists (of any type) into a single list of that type concat :: [[a]] -> [a]

*Operator sections: (2+) (+2) (a:) (++\n) E.g. (3+) 5 = 3 + 5 = 8 isEven = (==0) . (mod 2)*If we want to work with expressions like this, then it's only really possible if we work with the structure, rather than the string.

*Parsing : Aim to read a string like "((2+3)-4)" and produce the structure Minus (Sum (Lit 2) (Lit 3)) (Lit 4)

Naming abstract syntax trees : term trees*Recursion calls on substructure ; easy to isolate substructure through pattern matching than list processing (cf. Scheme)*Expression with variables requires environment**Novel way of defining lists : cf. set comprehensionScope of variables following | is the list-comprehension expression. books db br = [ bk | (per,bk) [a]Main> qsort [1,3,2,1][1,1,2,3] *n(log n) : best, average, worst ***Declarative programming : Equational reasoning (Interpreter Implementation???)Syntax: End of a definition explicitly given as ; or through indentation by making the body of the definition start a little to the right of the first col on first line. OFFSIDE RULE.--------------------------------Evaluate as needed : take 100 (nums 1)*Infix to prefix operator: (+) 2 3 = 2 + 3Prefix to infix operator: mod 2 3 = 2 mod 3Lots more examples in the code for the book, Chapter 17.

Recommended