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

○ 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 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 ● ● Lazy Evaluation Higher-order function

Function that ● takes a function as input or ● outputs a function Higher-order function

Examples: ● Differentiation ○ (λ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

● Anonymous function ● Currying ● Higher-order function ● Pure function ● Referential transparency ● Lazy Evaluation Functional programming in C++?

#include ● 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 => a -> a -> a fst :: (a, b) -> a snd :: (a, b) -> b div :: Integral a => a -> a -> a mod :: Integral a => a -> a -> a even :: Integral a => a -> Bool odd :: Integral a => a -> Bool Prelude 2 of 5 sum :: Num a => [a] -> a product :: Num a => [a] -> a maximum :: Ord a => [a] -> a minimum :: Ord a => [a] -> a take :: Int -> [a] -> [a] drop :: Int -> [a] -> [a] takeWhile :: (a -> Bool) -> [a] -> [a] dropWhile :: (a -> Bool) -> [a] -> [a] Prelude 3 of 5 head :: [a] -> a last :: [a] -> a init :: [a] -> [a] tail :: [a] -> [a] length :: [a] -> Int reverse :: [a] -> [a] (++) :: [a] -> [a] -> [a] concat :: [[a]] -> [a] repeat :: a -> [a] Prelude 4 of 5 map :: (a -> b) -> [a] -> [b] -- C++ std::transform filter :: (a -> Bool) -> [a] -> [a] foldl :: (b -> a -> b) -> b -> [a] -> b foldr :: (a -> b -> b) -> b -> [a] -> b -- foldr (+) 0 [1,2,3,4,5] == 15 -- C++ std::accumulate Prelude 5 of 5 words :: String -> [String] -- words "Have a nice \n day" == ["Have","a","nice","day"] unwords :: [String] -> String -- unwords ["Have","a","nice","day"] == "Have a nice day" lines :: String -> [String] -- lines "One \nTwo\n\nThree" == ["One ","Two","","Three"] unlines :: [String] -> String -- unlines ["One ","Two","","Three"] = "One \nTwo\n\nThree\n" read :: String -> a -- read "123" == 123 show :: a -> String -- show 123 == "123" hello, world main = interact pureMain pureMain :: String -> String pureMain _ = "hello, world" plus one main = interact pureMain pureMain :: String -> String pureMain s = show (read s + 1) A+B problem main = interact pureMain pureMain :: String -> String pureMain s = show (read a + read b) where [a,b] = words s sum problem main = interact pureMain pureMain :: String -> String pureMain s = show (sum list) where list = map read (words s) sum problem main = interact pureMain pureMain :: String -> String pureMain s = show (sum (map read (words s))) sum problem main = interact pureMain pureMain :: String -> String pureMain s = (show . sum . map read . words) s sum problem main = interact pureMain pureMain :: String -> String pureMain = show . sum . map read . words sum problem main = interact (show . sum . map read . words) sum problem main = interact $ show . sum . map read . words

-- ($) :: (a -> b) -> a -> b quick sort main = interact $ unwords . map show . qsort . map read . words qsort :: [Int] -> [Int] qsort (n:ns) = qsort left ++ [n] ++ qsort right where left = filter (< n) ns right = filter (>= n) ns qsort [] = [] sort import Data.List main = interact $ unwords . map show . sort . map read . words fib - revisited main = interact $ show . fib . read

-- exponential time fib :: Integer -> Integer fib 0 = 1 fib 1 = 1 fib n = fib (n - 1) + fib (n - 2) fib - revisited main = interact $ show . fib . read fib :: Integer -> Integer fib 0 = 1 fib 1 = 1 fib n = fibs 1 1 n fibs :: Integer -> Integer -> Integer -> Integer fibs a b 0 = b fibs a b n = fibs b (a + b) (n - 1) https://wiki.haskell.org/The_Fibonacci_sequence Before we end, remember this? Rewrite it in simpler Haskell :p import Data.List main = interact $ (++ "\n") . unwords . map show . f . map read . words zero :: [Int] zero = concat [[x,-x] | x <- [1..]] f :: [Int] -> [Int] f [n, 0] | even n = take n zero f [n, m] | even n = take n (0 : m : (zero \\ [m, -m])) | odd n = take n ( m : (zero \\ [m, -m]))