11/28/17 CSCI-2320 Functional Programming with Haskell Mohammad T . Irfan Functional Programming u Mimic mathematical functions u No variables in C/Java sense u No assignment statements in C/Java sense u How about loops? u Context-independent u Referential transparency u A function depends only on its arguments and nothing else u Other prime features u Functions are first-class citizens u Extensive polymorphism u List types and operators u Recursion 1
11/28/17 "It certainly seems like the kind of cognitive act that we are unlikely to see from any other species." – John R. Anderson (Psychologist, CMU) on recursion Functional Programming “Backus’s apology for creating FORTRAN” Check it out on Blackboard 2
11/28/17 Interesting facts: LISP and LISP Machine John McCarthy Knight machine LISP(1960) (1980s) Haskell 3
11/28/17 Resources u Installation u http://www.haskell.org/platform/ u Haskell (GHCi) commands u http://www.haskell.org/ghc/docs/7.4.1/html/ users_guide/ghci-commands.html u Learning u Best book: Miran Lipovaca’s Learn You a Haskell for Great Good! u http://learnyouahaskell.com/ (free online version) u Useful how-to page u http://www.haskell.org/haskellwiki/Category:How_to u Other resources: http://www.haskell.org/haskellwiki/Learning_Haskell 4
11/28/17 Haskell Warm-up exercises Elementary functions u Make a myFunctions.hs file and define the following functions in it u doubleMe x = x + x u addSquares x y = x*x + y*y u Using the terminal go to the folder of that .hs file u Execute this command: ghci u Load the .hs file u :load myFunctions.hs (or, :l myFunctions.hs) u Use your functions u addSquares 5 10 u If you change the .hs file => Execute :r to reload 5
11/28/17 if-then-else u Indentation is important if boolean then expr1 else expr2 u Same line is fine if boolean then expr1 else expr2 u else is a must! Following doesn’t make sense: u let x = if a then b u Nested if? Yes! u Close alternative to if-then-else u “guard” Problem: calculate factorial of n Version 1 – note indentation factorialV1 n = if n == 0 then 1 else if n > 0 then n * factorialV1(n-1) else 0 6
11/28/17 Factorial Version 2 – using guard u factorial n | n == 0 = 1 | n > 0 = n * factorial (n-1) -- why not factorial n – 1 ? Guard u Try this: factorial 100 Problem: n-th Fibonacci number fib n | n == 0 = 1 | n == 1 = 1 | n > 1 = fib (n-1) + fib (n-2) | otherwise = 0 Alias for True u Can you solve it using if-then-else? u How about memoized version of fibonacci? 7
11/28/17 List u Want: evens = [0, 2, 4, 6, 8, 10] u In terminal (ghci) u let evens = [0, 2 .. 10] u let evens = [2*x | x <- [0..5] ] u Infinite list let for defining functions u let allEvens = [0, 2 ..] within terminal or within another functions Are these assignment statements? Is it a loop? x <- [0..5] u No; recursion is the key! u evens1 list = [2*x | x <- list] u evens2 [] = [] u evens2 (x:xs) = [2*x] ++ evens2 xs 8
11/28/17 Anatomy of a list u Two parts u head u List of the remaining elements (AKA tail) u Functions head and tail return these u head evens u tail evens u Joining head and tail by : operator u 0 : [2, 4 .. 10] will give [0, 2, 4, 6, 8, 10] u Indexing function is !! u evens !! 2 u Reference u http://www.haskell.org/haskellwiki/How_to_work_on_lists Problem: sort a list (low to high) sort [] = [] Empty list sort (head:remainingList) = sort [b | b <- remainingList, b < head] ++ [head] ++ sort [b | b <- remainingList, b >= head] List generator 9
11/28/17 More list examples u Example: Factors of a number n u factors n = [f | f <- [1 .. n], mod n f == 0] u Example: Compute ALL prime numbers! u primes = primeGen' [2 ..] where primeGen' (p:xs) = p : primeGen' [q | q <- xs, mod q p /= 0] -- same line u Getting the first 10 prime numbers u take 10 primes Lazy evaluation u Side note: This is not really the sieve of Eratosthenes http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP .pdf Problem solving using Haskell Main ingredient: recurrence relation u Recursive sum u recSum [] = 0 recSum (x:xs) = x + recSum xs u Built-in function that does the above: sum u sum [1 .. 5] u Similar built-in function: product u factorial n = product [1 .. n] 10
11/28/17 Higher-order function/ curried function u One function can be a parameter of another functions u One function can return another function Haskell Curry Higher-order function/ curried function u In GHCI command area: let fun3 x y z = x+y-z -- 3 param function fun3 1 2 3 – outputs 0 Comment u This is how Haskell deals with the fun3 function: let fun2 = fun3 1 -- 2 param function let fun1 = fun2 2 -- 1 param function fun1 3 -- outputs 0 11
11/28/17 n-queens problem Generate all possible solutions queens n = solve n where solve k | k <= 0 = [ [] ] | otherwise = [ h:partial | partial <- solve (k-1), h <- [0..(n-1)], safe h partial] safe h partial = and [ not ( checks h partial i) | i <- [0..(length partial - 1)]] checks h partial i = h == partial!!i || abs(h - partial!!i) == i+1 Useful built-in functions 1. map function list u map ( > 0) [2, -50, 100] -- à [True, False, True] u Equivalent: [ x > 0 | x <- [2, -50, 100] ] u map (`mod` 2) [13, 14, 15] -- à [1, 0, 1] 2. filter condition list u Examples u Sorting function (from last class) qsort [b| b<-xs, b<x] qsort [] = [] qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++ Difference between qsort (filter (>= x) xs) map and filter? 12
11/28/17 Useful built-in functions 3. Fold: produces single value from a list (From Haskell.org) Binary function Accumulator! u foldl f z [] = z foldl f z (x:xs) = foldl f (f z x) xs u foldr f z [] = z foldr f z (x:xs) = f x (foldr f z xs) u Example u foldl (-) 1 [2, 3, 4] u foldr (-) 1 [2, 3, 4] u anyTrue = foldr (||) False [True, True ..] u anyTrue = foldl (||) False [True, True ..] Useful built-in functions u zipWith u Arguments: a function and two lists u Applies that function to the corresponding elements of the list and produces a new list ghci> zipWith (+) [1,2,3,4] [5,6,7,8] [6,8,10,12] ghci> zipWith max [6,3,2,1] [7,3,1,5] [7,3,2,5] ghci> zipWith (++) ["foo ", "bar ", "baz "] ["fighters", "hoppers", "aldrin"] ["foo fighters","bar hoppers","baz aldrin"] 13
11/28/17 Additional practice: Evaluate Polish prefix expression u 10 + (15 – 5) * 4 u + 10 * - 15 5 4 u 10 + 15 – 5 * 4 u + 10 - 15 * 5 4 u Input: String (list of characters) of Polish prefix expression u Output: Value of expression u Solution u Reverse the expr foldl u Traverse it from left to right u Stack operations (implement by a list: head is TOS) u If the current string is an operator, pop the top two operands and push the result of applying the operator Solution evaluate expr = head(foldl stackOperation [] (reverse(words(expr)))) where stackOperation (x:y:xs) curString | curString == "+" = (x+y):xs | curString == "-" = (x-y):xs | curString == "*" = (x*y):xs stackOperation xs curString = read curString:xs 14
11/28/17 Alternative solution evaluatePrefix expr = head ( foldl f [] ( reverse (words expr) ) ) where f (x:y:ys) "*" = (x*y):ys f (x:y:ys) "+" = (x+y):ys f (x:y:ys) "-" = (x-y):ys f xs str = read str:xs Additional practice: Memoization for Fibonacci -- Memoized fibonacci numbers fibs = [fibMem n | n <- [0..]] --infinite list fibMem n | n == 0 = 1 | n == 1 = 1 | otherwise = fibs!!(n-1) + fibs!!(n-2) 15
11/28/17 Theoretical foundation: λ calculus u Optional reading: Scott’s section 11.2.4* (on Blackboard) u Alonzo Church's λ calculus u Goal: express computation using mathematical functions [1936—1940] u Think about sqrt: R à R u Where's the algorithm? u Key ideas in λ calculus u Function abstraction and application u Name/"variable" binding and substitution u λ calculus examples u λ x . x * x * x (known as λ abstraction) u ( λ x . x * x * x) 2 (known as function application) u yields 8 Building block: λ expression (expr) Recursive definition u A name u times (that is, arithmetic * operation) u x u (expr) u A λ abstraction: λ name.expr u λ x.x (identity) u λ x.5 (constant) u λ x.times x x (times x x is another expr– see below) u A function application: two adjacent expr, the first is a function applied to the second u times x x <--> curried function (times x) x 16
11/28/17 Example u Can name λ expressions u e.g., hypotenuse below u hypotenuse = λ x. λ y.sqrt (plus (square x) (square y) ) u hypotenuse 3 4 u yields 5 u How? By substitution: x = 3, y = 4 (an instance of "beta reduction") u Two other rules u alpha conversion: nothing changes if you rename a "variables" (under certain conditions) u eta reduction: if E has nothing to do with x in λ x.E, then λ x.E is the same as just E 17
Recommend
More recommend