1 / 41

Functional Programming in Haskell

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,

shada
Télécharger la présentation

Functional Programming in Haskell

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


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

  2. Functional Programming • Given the functions • above invertColour flipH • sideBySide superimpose flipV • and the horse picture, • how do you get … (expression and evaluation) L5-Haskell

  3. Definitions in Haskell • name :: Type • name = expression • blackHorse :: Picture • blackHorse = invertColour horse • rotate :: Picture -> Picture • rotate pic = flipH (flipV pic) 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. L5-Haskell

  5. Declarative … proofs possible • Programs describe themselves: • square n = n*n double n = 2*n • 'The square of nisn*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

  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? 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). 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/ L5-Haskell

  9. If we reach here they're not all equal … … and if we reach here they're all different. 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 L5-Haskell

  10. How many pieces with n cuts? L5-Haskell

  11. 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 L5-Haskell

  12. The Pictures case study. • Using a powerful library of functions over lists. • Pattern matching • Recursion • Generic functions • Higher-order functions • … L5-Haskell

  13. Using Hugs • exprEvaluate 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 L5-Haskell

  14. input output Functions over pictures • A function to flip a picture in a vertical mirror: flipV L5-Haskell

  15. invertColour Functions over pictures • A function to invert the colours in a picture: L5-Haskell

  16. Functions over pictures • A function to superimpose two pictures: superimpose L5-Haskell

  17. Functions over pictures • A function to put one picture above another: above L5-Haskell

  18. Functions over pictures • A function to put two pictures side by side: sideBySide L5-Haskell

  19. 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). .......##... .....##..#.. ...##.....#. ..#.......#. ..#...#...#. ..#...###.#. .#....#..##. ..#...#..... ...#...#.... ....#..#.... .....#.#.... ......##.... L5-Haskell

  20. 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. L5-Haskell

  21. How are they implemented? • flipH reverse • flipV map reverse • rotate flipV . flipH • above ++ • sideBySide zipWith (++) • invertColour map (map invertChar) • superimpose zipWith (zipWith combine) L5-Haskell

  22. 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. L5-Haskell

  23. 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. L5-Haskell

  24. 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 L5-Haskell

  25. 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] L5-Haskell

  26. A function [[Char]]->[[Char]] A function [Char]->[Char] Partial application in Pictures • flipV = map reverse • invertColour = map (map invertChar) L5-Haskell

  27. Another pattern: zipping together sideBySide [l1,l2,l3] [r1,r2,r3] = [ l1++r1, l2++r2, l3++r3 ] zipWith f (x:xs) (y:ys) = f x y : zipWith f xs ys zipWith f xs ys = [] zipWith :: (a->b->c) -> [a] -> [b] -> [c] L5-Haskell

  28. 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) L5-Haskell

  29. Parsing • "((2+3)-4)" • is a sequence of symbols, but underlying it is a structure ... - + 4 2 3 L5-Haskell

  30. 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) L5-Haskell

  31. 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) L5-Haskell

  32. 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 L5-Haskell

  33. 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 L5-Haskell

  34. 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 them • 6 4 • giving the result • [6,4] L5-Haskell

  35. 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 pairs • 16 21 15 20 14 19 • giving the result • [16,21,15,20,14,19] L5-Haskell

  36. 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] L5-Haskell

  37. 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 L5-Haskell

  38. Merging x x <= y? 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

  39. Defining Merge One list gets smaller. 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 Two possible base cases. L5-Haskell

  40. 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 L5-Haskell

  41. 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 xswith all multiples of x removed. L5-Haskell

More Related