Pattern Matching
Total Page:16
File Type:pdf, Size:1020Kb
Functional Programming Steven Lau March 2015 before function programming... https://www.youtube.com/watch?v=92WHN-pAFCs Models of computation ● Turing machine ○ invented by Alan Turing in 1936 ● Lambda calculus ○ invented by Alonzo Church in 1930 ● more... Turing machine ● A machine operates on an infinite tape (memory) and execute a program stored ● It may ○ read a symbol ○ write a symbol ○ move to the left cell ○ move to the right cell ○ change the machine’s state ○ halt Turing machine Have some fun http://www.google.com/logos/2012/turing-doodle-static.html http://www.ioi2012.org/wp-content/uploads/2011/12/Odometer.pdf http://wcipeg.com/problems/desc/ioi1211 Turing machine incrementer state symbol action next_state _____ state 0 __1__ state 1 0 _ or 0 write 1 1 _10__ state 2 __1__ state 1 0 1 write 0 2 _10__ state 0 __1__ state 0 _00__ state 2 1 _ left 0 __0__ state 2 _00__ state 0 __0__ state 0 1 0 or 1 right 1 100__ state 1 _10__ state 1 2 0 left 0 100__ state 1 _10__ state 1 100__ state 1 _10__ state 1 100__ state 1 _10__ state 0 100__ state 0 _11__ state 1 101__ state 1 _11__ state 1 101__ state 1 _11__ state 0 101__ state 0 λ-calculus Beware! ● think mathematical, not C++/Pascal ● (parentheses) are for grouping ● variables cannot be mutated ○ x = 1 OK ○ x = 2 NO ○ x = x + 1 NO λ-calculus Simplification 1 of 2: ● Only anonymous functions are used ○ f(x) = x2+1 f(1) = 12+1 = 2 is written as ○ (λx.x2+1)(1) = 12+1 = 2 note that f = λx.x2+1 λ-calculus Simplification 2 of 2: ● Only unary functions are used ○ a binary function can be written as a unary function that return another unary function ○ (λ(x,y).x+y)(1,2) = 1+2 = 3 is written as [(λx.(λy.x+y))(1)](2) = [(λy.1+y)](2) = 1+2 = 3 ○ this technique is known as Currying Haskell Curry λ-calculus ● A lambda term has 3 forms: ○ x ○ λx.A ○ AB where x is a variable, A and B are lambda terms. Church-Turing thesis ● Conjectures that Turing machines can simulate all computers ● Generally believed to be true ● A programming language that can simulate a Turing machine is said to be Turing-complete ○ Any examples? ○ C, C++, Pascal, most programming languages ○ English, Cantonese ○ lambda calculus 2 branches ● Turing machine: imperative programming ● Lambda calculus: functional programming Functional Programming We all know function Constant function f(x) = 2 Identity function id(y) = y Quadratic function g(x) = x2+5 more new terms ● Anonymous function ● Currying ● Higher-order function ● Pure function ● Referential transparency ● Lazy Evaluation Higher-order function Function that ● takes a function as input or ● outputs a function Higher-order function Examples: ● Differentiation ○ D(λx.x2+3) = λx.2x ● std::sort (C++) ○ sort(a, a + N, cmp); ● Curried functions ○ (λx.(λy.x+y))(1) = λy.1+y ○ also known as partial application Pure function A function is pure if it, ● always evaluates the same result given the same argument(s) ● does not cause side effects (e.g. output) Pure function A function is pure if it, ● always evaluates the same result given the same argument(s) ● does not cause side effects (e.g. output) pure functions: sin, strlen, max impure functions: rand, printf Pure function A function is pure if it, ● always evaluates the same result given the same argument(s) ● does not cause side effects (e.g. output) These properties are also called "referential transparency” Referential transparency ● helps reasoning behaviour ● assists modifying codes ● allows optimizations such as ○ memoization ○ parallelism ○ lazy evaluation Referential transparency ● helps reasoning the behaviour ● assists modifying codes ● allows optimizations such as ○ memoization ○ parallelism ○ lazy evaluation Lazy evaluation 1000000000 let f(x) = x mod 10 10 g(x) = 3 h(x) = g(f(x))2+2g(4) - x Evaluate h(5). Good trainees: Oh, Big Mod. #include <cstdi... Better trainees: Observe that 5k mod 10 = 5 for k ≥ 1, … Lazy trainees: Zzz... more new terms ● Anonymous function ● Currying ● Higher-order function ● Pure function ● Referential transparency ● Lazy Evaluation Functional programming in C++? #include <functional> ● Anonymous function available in C++11 ● Higher-order function implemented as function pointer or function object ● Partial application only for binary functions ○ std::bind1st Functional programming in ... Haskell The root Haskell ● (\x -> x^2 + 1)(1) ● (\x -> (\y -> x + y))(1)(2) Remember λ-calculus? ● (λx.x2+1)(1) ● (λx.(λy.x+y))(1)(2) Haskell Basics ● Variables ○ value ○ list ○ tuple ○ lambda function ○ where ○ let in ● Functions ● Control Structures ● More on types Variables - value k :: Double k = 0.5 l :: Int l = 2147483647 m :: Integer m = 1230193729237469187264987702987109823741052873452698734659187345928743501976 myExamGrade = ('A' :: Char) Variables - list k :: [Int] -- a list of Ints k = [1,2,3,4] l :: [[Int]] -- a list of lists of Ints l = [[1,2],[],k,[1]] s :: [Char] s = ['a','b','c'] -- s = "abc" Variables - list k :: [Int] -- a list of Ints k = 1:2:3:4:[] l :: [[Int]] -- a list of lists of Ints l = (1:2:[]):[]:k:(1:[]):[] s :: [Char] s = 'a':'b':'c':[] -- s = "abc" Variables - list k :: [Int] k = 1:2:3:4:[] k' :: [Int] k' = -1:0:k -- k' = [-1,0,1,2,3,4] Variables - list k :: [Int] k = [1..4] -- k = [1,2,3,4] l :: [Int] l = [1,3..9] -- l = [1,3,5,7,9] m :: [Integer] m = [1..] -- infinite list begin = 'a' end = 'z' alphabet = [begin..end] -- alphabet = "abcdefghijklmnopqrstuvwxyz" Variables - list comprehension s = [2 * x | x <- [0..], x^2 > 3] -- s = [4,6,8,10,......] digits = [x * y | x <- [1,2,3], y <- [1,2,3,4]] -- digits = [1,2,3,4,2,4,6,8,3,6,9,12] Variables - tuple a :: ([Char], Int, Char) a = ("Hello", 567, 'k') b :: Int -- b is NOT a tuple b = (123) c :: () -- c is a tuple c = () Variables - function f :: Int -> Int f = \x -> x^2 + 2*x + 1 k :: Int k = f 4 g :: Char -> Char -> [Char] g = \a b -> [a, b] g' = \a -> (\b -> [a, b]) k' :: [Char] k' = g 'm' 'n' Variables - where k :: Int k = x^2 + 3 where x = 2 l :: Int l = f 2 3 + g 4 5 where f = \x y -> x + y g = \x y -> x * y Variables - let in k :: Int k = (let x = 2 in x^2 + 3) l :: Int l = let f = \x y -> x + y g = \x y -> x * y in f 2 3 + g 4 5 Haskell Basics ● Variables ● Functions ○ more than λ ○ partial application ○ operator ○ infix function ○ guard ○ pattern matching ○ function composition ● Control structures ● More on types Functions - more than λ k :: Int -- nullary function, aka constant k = 1 f :: Int -> Int -- unary function f x = x + 1 -- f = \x -> x + 1 g :: Int -> (Int -> Int) -- binary function g x y = x + y -- g = \x y -> x + y Functions - partial application plus :: Int -> Int -> Int plus x y = x + y plusOne :: Int -> Int plusOne x = plus 1 x plusOne' :: Int -> Int plusOne' = plus 1 Functions - operators k :: Int k = (+) 2 1 l :: Int l = (-) 2 1 m :: [Int] m = (:) 1 [2,3,4] Functions - operators -- partial application also works plusOne :: Int -> Int plusOne = (+) 1 plusOne' = (1 +) plusOne'' = (+ 1) divideTwo :: Double -> Double divideTwo = (/ 2) oneMinus = (-) 1 :: Int -> Int oneMinus' = (1 -) :: Int -> Int minusOne = (- 1) :: Int -- not partial application Functions - infix function minus :: Int -> (Int -> Int) minus x y = x - y k :: Int k = 1 `minus` 2 -- only works for binary function -- k = minus 1 2 *note the backtick used Functions - infix function minus :: Int -> (Int -> Int) minus x y = x - y oneMinus :: Int -> Int oneMinus = (1 `minus`) minusOne :: Int -> Int minusOne = (`minus` 1) Functions - guards sgn :: Int -> Int sgn x | x > 0 = 1 | x == 0 = 0 | x < 0 = (-1) f :: Int -> [Char] f x | x /= 1 = "not one" | x /= 2 = "not two" | otherwise = "otherwise" Functions - pattern matching fib :: Integer -> Integer fib 0 = 1 fib 1 = 1 fib n = fib (n - 1) + fib (n - 2) Functions - pattern matching head :: [Int] -> Int head (a:as) = a fst :: (Int,Int) -> Int fst (a,b) = a polite :: [Char] -> [Char] polite ('h':'i':s) = 'h':'e':'l':'l':'o':s Functions - function composition f :: Int -> Int f = (^2) g :: Int -> Int g = (+1) k :: Int k = (g . f)(3) Functions - function composition p :: a -> (a, a) p x = (x, x) h :: (a, a) -> Bool -- unknown implementation n :: Bool -> Bool n True = False n False = True x :: a -> Bool x = n . h . p Haskell Basics ● Variables ● Functions ● Control structures ○ if-then-else ○ case of ● More on types Control structures - if-then-else k :: [Char] k = (if 1 + 1 == 2 then "correct" else "incorrect") Control structures - case of k :: [Char] k = (case 1 + 1 of 2 -> "two" 3 -> "not two") arity :: Int -> [Char] arity x = (case x of 0 -> "nullary" 1 -> "unary" 2 -> "binary") Haskell Basics ● Variables ● Functions ● Control structures ● More on types ○ type variables ○ type constraints ○ strong static typing More on types - type variables length' :: [a] -> Int length' (a:as) = 1 + length as length' [] = 0 reverse' :: [a] -> [a] reverse' a = reverse'' a [] where reverse'' (a:as) b = reverse'' as (a:b) reverse'' [] b = b More on types - type constraints (+) :: Num a => a -> a -> a (/) :: Fractional a => a -> a -> a (==) :: Eq a => a -> a -> Bool (:) :: a -> [a] -> [a] (.) :: (b -> c) -> (a -> b) -> (a -> c) ($) :: (a -> b) -> a -> b More on types - strong static typing ● All variables' types are known at compile time ● All function applications have matching types ● Avoids many stupid bugs More on types - strong static typing ● if you can compile, you are probably correct! Haskell standard libraries ● Prelude (imported by default) ● Data.List ● Data.Char https://downloads.haskell.org/~ghc/7.6-latest/docs/html/libraries/index.html Prelude 1 of 5 max :: Ord a => a -> a -> a min :: Ord a