Functional Programming in Haskell

Download Functional Programming    in Haskell

Post on 07-Jan-2016




8 download

Embed Size (px)


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 Presentation


<ul><li><p> Functional Programming in Haskell</p><p> Motivation through Concrete Examples </p><p>Adapted from Lectures bySimon Thompson</p><p>L5-Haskell</p></li><li><p>CS7120 (Prasad)L5-Haskell*Functional Programming Given the functionsabove invertColour flipH sideBySide superimpose flipVand the horse picture, how do you get </p><p>(expression and evaluation)</p><p>L5-Haskell</p></li><li><p>CS7120 (Prasad)L5-Haskell*Definitions in Haskellname :: Typename = expression </p><p>blackHorse :: PictureblackHorse = invertColour horse</p><p>rotate :: Picture -&gt; Picturerotate pic = flipH (flipV pic)</p><p>L5-Haskell</p></li><li><p>CS7120 (Prasad)L5-Haskell*Higher-levelEvaluation is about expressions and values, not storage locations.</p><p> No need to allocate/deallocate storage: garbage collection.</p><p> 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.</p><p>L5-Haskell</p></li><li><p>CS7120 (Prasad)L5-Haskell*Declarative proofs possiblePrograms describe themselves: square n = n*n double n = 2*n</p><p>'The square of n is n*n, for every integer n.'Programs are equations.So we can write proofs using the definitions.</p><p>square (double n) = square (2*n) = (2*n)*(2*n) = 2*2*n*n= double (double (square n))</p><p>L5-Haskell</p></li><li><p>CS7120 (Prasad)L5-Haskell*Evaluation freedomEvaluation can occur in any order ...</p><p> (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).</p><p>Can also evaluate in parallel efficiently?</p><p>L5-Haskell</p></li><li><p>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.</p><p>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).</p><p>L5-Haskell</p></li><li><p>CS7120 (Prasad)L5-Haskell*Haskell and HugsNamed after Haskell Brooks Curry: mathematician and logician; inventor of the -calculus. </p><p>Haskell 98 is the recent 'standard' version of Haskell.</p><p>Various implementations: Hugs (interpreter for Windows, Mac, Unix) and GHC, NHC, HBC (compilers). </p><p></p><p>L5-Haskell</p></li><li><p>Basics: guards and base typesHow many of three integers are equal ?</p><p>howManyEqual :: Int -&gt; Int -&gt; Int -&gt; Int</p><p>howManyEqual n m k | n==m &amp;&amp; m==k = 3 | n==m || m==k || k==n = 2 | otherwise = 1CS7120 (Prasad)L5-Haskell*</p><p>L5-Haskell</p></li><li><p>CS7120 (Prasad)L5-Haskell*Regular and literate scriptsIn a regular script there are definitions and comments:</p><p>-- FirstScript.hs-- 5 October 2000</p><p>-- Double an integer.</p><p>double :: Int -&gt; Intdouble n = 2*n</p><p>Everything is program, except comments beginning --. In a literate script there are comments and definitions: </p><p>FirstLit.lhs5 October 2000</p><p>Double an integer.</p><p>&gt; double :: Int -&gt; Int&gt; double n = 2*n</p><p>Everything is comment, except program beginning &gt; .</p><p>L5-Haskell</p></li><li><p>CS7120 (Prasad)L5-Haskell*How many pieces with n cuts?</p><p>L5-Haskell</p></li><li><p>CS7120 (Prasad)L5-Haskell*How many pieces with n cuts?No cuts: 1 piece.</p><p>With the nth cut, you get n more pieces:</p><p>cuts :: Int -&gt; Intcuts n | n==0 = 1 | n&gt;0 = cuts (n-1) + n | otherwise = 0 </p><p>L5-Haskell</p></li><li><p>CS7120 (Prasad)L5-Haskell*The Pictures case study.</p><p>Using a powerful library of functions over lists. Pattern matching Recursion Generic functions Higher-order functions </p><p>L5-Haskell</p></li><li><p>CS7120 (Prasad)L5-Haskell*Using Hugs</p><p> 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 </p><p>L5-Haskell</p></li><li><p>CS7120 (Prasad)L5-Haskell*Functions over picturesA function to flip a picture in a vertical mirror:flipV</p><p>L5-Haskell</p></li><li><p>CS7120 (Prasad)L5-Haskell*Functions over picturesA function to invert the colours in a picture:</p><p>L5-Haskell</p></li><li><p>CS7120 (Prasad)L5-Haskell*Functions over picturesA function to superimpose two pictures:superimpose</p><p>L5-Haskell</p></li><li><p>CS7120 (Prasad)L5-Haskell*Functions over picturesA function to put one picture above another:above</p><p>L5-Haskell</p></li><li><p>CS7120 (Prasad)L5-Haskell*Functions over picturesA function to put two pictures side by side:sideBySide</p><p>L5-Haskell</p></li><li><p>CS7120 (Prasad)L5-Haskell*A nave implementationtype Picture = [String]type String = [Char]</p><p>A Picture is a list of Strings.A String is a list of Char (acters)........##........##..#.....##.....#...#.......#...#...#...#...#...###.#..#....#..##...#...#........#...#........#..#.........#.#..........##.... </p><p>L5-Haskell</p></li><li><p>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.</p><p>L5-Haskell</p></li><li><p>CS7120 (Prasad)L5-Haskell*How are they implemented?flipHreverseflipVmap reverserotateflipV . flipH above++sideBySidezipWith (++)invertColourmap (map invertChar)superimposezipWith (zipWith combine)</p><p>L5-Haskell</p></li><li><p>CS7120 (Prasad)L5-Haskell*Lists and typesHaskell is strongly typed: detect all type errors before evaluation.</p><p>For each type t there is a type [t], 'list of t'.</p><p>reverse [] = []reverse (x:xs) = reverse xs ++ [x]</p><p>reverse :: [a] -&gt; [a]</p><p>a is a type variable: reverse works over any list type, returning a list of the same type.</p><p>L5-Haskell</p></li><li><p>CS7120 (Prasad)L5-Haskell*Flipping in a vertical mirrorflipV :: Picture -&gt; Picture</p><p>flipV [] = []flipV (x:xs) = reverse x : flipV xs</p><p>Run along the list, applying reverse to each element</p><p>Run along the list, applying to every element.</p><p>General pattern of computation.</p><p>L5-Haskell</p></li><li><p>CS7120 (Prasad)L5-Haskell*Implementing the mapping patternmap f [] = []map f (x:xs) = f x : map f xs</p><p>map :: (a -&gt; b) -&gt; [a] -&gt; [b]</p><p>Examples over pictures:</p><p>flipV pic = map reverse picinvertColour pic = map invertLine picinvertLine line = map invertChar line</p><p>L5-Haskell</p></li><li><p>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. </p><p>map isEven = ??map isEven :: [Int] -&gt; [Bool]</p><p>It is a partial application, which gives a function:give it a [Int] and it will give you back a [Bool]</p><p>L5-Haskell</p></li><li><p>CS7120 (Prasad)L5-Haskell*Partial application in PicturesflipV = map reverse</p><p>invertColour = map (map invertChar)</p><p>L5-Haskell</p></li><li><p>CS7120 (Prasad)L5-Haskell*Another pattern: zipping togethersideBySide [l1,l2,l3] [r1,r2,r3] = [ l1++r1, l2++r2, l3++r3 ]zipWith :: (a-&gt;b-&gt;c) -&gt; [a] -&gt; [b] -&gt; [c]zipWith f (x:xs) (y:ys) = f x y : zipWith f xs ys</p><p>zipWith f xs ys = []</p><p>L5-Haskell</p></li><li><p>CS7120 (Prasad)L5-Haskell*In the case study sideBySide = zipWith (++)</p><p>Superimposing two pictures: need to combine individual elements:</p><p>combine :: Char -&gt; Char -&gt; Charcombine top btm = if (top=='.' &amp;&amp; btm=='.') then '.' else '#'</p><p>superimpose = zipWith (zipWith combine)</p><p>L5-Haskell</p></li><li><p>CS7120 (Prasad)L5-Haskell*Parsing "((2+3)-4)"</p><p>is a sequence of symbols, but underlying it is a structure ...-423+</p><p>L5-Haskell</p></li><li><p>CS7120 (Prasad)L5-Haskell*Arithmetical expressionsAn expression is either</p><p> a literal, such as 234 or a composite expression:</p><p> the sum of two expressions (e1+e2)</p><p> the difference of two expressions (e1-e2)</p><p> the product of two expressions (e1*e2)</p><p>L5-Haskell</p></li><li><p>CS7120 (Prasad)L5-Haskell*How to represent these structures?data Expr = Lit Int | Sum Expr Expr | Minus Expr Expr | Times Expr Expr</p><p>Elements of this algebraic data type include</p><p>Lit 3434Sum (Lit 45) (Lit 3)(45+3)Minus (Sum (Lit 2) (Lit 3)) (Lit 4)((2+3)-4)</p><p>L5-Haskell</p></li><li><p>CS7120 (Prasad)L5-Haskell*Counting operatorsdata Expr = Lit Int | Sum Expr Expr | Minus ...</p><p>How many operators in an expression?</p><p>Definition using pattern matching</p><p>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</p><p>L5-Haskell</p></li><li><p>CS7120 (Prasad)L5-Haskell*Evaluating expressionsdata Expr = Lit Int | Sum Expr Expr | Minus ...</p><p>Literals are themselves </p><p>eval (Lit n) = n</p><p> in other cases, evaluate the two arguments and then combine the results </p><p>eval (Sum e1 e2) = eval e1 + eval e2eval (Minus e1 e2) = eval e1 - eval e2eval (Times e1 e2) = eval e1 * eval e2</p><p>L5-Haskell</p></li><li>CS7120 (Prasad)L5-Haskell*List comprehensionsExample list x = [4,3,2,5][ n+2 | n</li><li>CS7120 (Prasad)L5-Haskell* List comprehensionsExample lists x = [4,3,2] y = [12,17][ n+m | n</li><li><p>CS7120 (Prasad)L5-Haskell*Quicksortqsort [] = []qsort (x:xs) = qsort elts_lt_x ++ [x] ++ qsort elts_greq_x</p><p> where elts_lt_x = [y | y </p></li><li><p>CS7120 (Prasad)L5-Haskell*MergeSort mergeSort [] = []mergeSort [x] = [x]mergeSort xs | size &gt; 1 = merge (mergeSort front) (mergeSort back)where size = length xs `div` 2 front = take size xsback = drop size xs</p><p>L5-Haskell</p></li><li>CS7120 (Prasad)*Mergingxyx </li><li><p>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.</p><p>L5-Haskell</p></li><li><p>CS7120 (Prasad)L5-Haskell* Lazy evaluationOnly evaluate what is needed infinite lists</p><p>nums :: Int -&gt; [Int]nums n = n : nums (n+1)</p><p>sft (x:y:zs) = x+y</p><p>sft (nums 3)= sft (3: nums 4)= sft (3: 4: nums 5)= 7</p><p>L5-Haskell</p></li><li><p>CS7120 (Prasad)L5-Haskell*The list of prime numbersprimes = sieve (nums 2)</p><p>sieve (x:xs) = x : sieve [ z | z [a] -&gt; [a]Can join a list of lists (of any type) into a single list of that type concat :: [[a]] -&gt; [a]</p><p> *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.</p><p>*Parsing : Aim to read a string like "((2+3)-4)" and produce the structure Minus (Sum (Lit 2) (Lit 3)) (Lit 4)</p><p>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&gt; 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.</p></li></ul>