1 / 143

COMP313A Functional Programming (1)

COMP313A Functional Programming (1). Main Differences with Imperative Languages. Say more about what is computed as opposed to how Pure functional languages have no variables assignments other side effects Means no loops. Differences….

jane
Download Presentation

COMP313A Functional Programming (1)

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. COMP313AFunctional Programming (1)

  2. Main Differences with Imperative Languages • Say more about what is computed as opposed to how • Pure functional languages have no • variables • assignments • other side effects • Means no loops

  3. Differences… • Imperative languages have an implicit state (state of variables)that ismodified (side effect). • Sequencing is important to gain precise, deterministic control over the state • assignment statement needed to change the binding for a particular variable (alter the implicit state)

  4. Imperative factorialn:=x; a:=1;while n > 0 do begin a:= a * n; n := n-1; end;

  5. Differences • Declarative languages have no implicitstate • Program with expressions • The state is carried around explicitly • e.g. the formal parameter n in factorial • Looping is accomplished with recursion rather than sequencing

  6. Haskell fac ::Int -> Int fac n | n == 0 = 1 | n > 0 = fac(n-1) * n | otherwise = 0 Scheme (define fac (lambda (n) (if (= n 0) 1 (* n (fac (- n 1))))))

  7. Advantages • similar to traditional mathematics • referential transparency makes programs more readable • higher order functions give great flexibility • concise programs

  8. Referential Transparency • the value of a function depends only on the values of its parameters for example Haskell …x + x… where x = f a

  9. Evolution of Functional languagesLambda Calculus • Alonzo Church • Captures the essence of functional programming • Formalism for expressing computation by functions • Lambda abstraction • In Scheme • In Haskell (lx. + 1 x) (lambda(x) (+ 1 x))) add1 :: Int -> Int add1 x = 1 + x

  10. Lambda Calculus… • application of expressions • reduction rule that substitutes 2 for x in the lambda (beta reduction) (lx. + 1 x) 2 (lx. + 1 x) 2 Þ (+ 1 2) Þ 3 (lx. * x x) (+ 2 3) i.e. (+ 2 3) / x)

  11. Lambda Calculus… • (lx.E) • variable x is bound by the lambda • the scope of the binding is the expression E • (lx. + y x) • (lx. + y x)2 Þ (+ y 2) • (lx. + ((ly. ((lx. * x y) 2)) x) y) Þ

  12. Lambda Calculus… • Each lambda abstraction binds only one variable • Need to bind each variable with its own lambda. (lx. (ly. + x y))

  13. Lisp • McCarthy late 1950s • Used Lambda Calculus for anonymous functions • List processing language • First attempt built on top of FORTRAN

  14. LISP… • McCarthy’s main contributions were • the conditional expression and its use in writing recursive functions Scheme (define fac (lambda (n) (if (= n 0) 1 (if (> n 0) (* n (fac (- n 1))) 0)))) Scheme (define fac2 (lambda (n) (cond ((= n 0) 1) ((> n 0) (* n (fac2 (- n 1)))) (else 0)))) Haskell fac ::Int -> Int fac n | n == 0 = 1 | n > 0 = fac(n-1) * n | otherwise = 0 Haskell fac :: Int -> Int fac n = if n == 0 then 1 else if n > 0 then fac(n-1) * n else 0

  15. Lisp… 2. the use of lists and higher order operations over lists such as mapcar Scheme (define mymap (lambda (f a b) (cond ((and (null? a) (null? b)) '()) (else (cons (f (first a) (first b)) (mymap f (rest a) (rest b))))))) Haskell mymap :: (Int -> Int-> Int) -> [Int] -> [Int] ->[Int] mymap f [] [] = [] mymap f (x:xs) (y:ys) = f x y : mymap f xs ys add :: Int -> Int -> Int add x y = x + y Scheme (mymap + ’(3 4 6) ’(5 7 8)) Haskell mymap add [3, 4, 6] [5, 7, 8]

  16. Lisp • cons cell and garbage collection of unused cons cells Scheme (cons ’1 ’(3 4 5 7)) (1 3 4 5 7) Haskell cons :: Int -> [Int] -> [Int] cons x xs = x:xs Scheme (define mymap (lambda (f a b) (cond ((and (null? a) (null? b)) '()) (else (cons (f (first a) (first b)) (mymap f (first a) (first b)))))))

  17. Lisp… • use of S-expressions to represent both program and data An expression is an atom or a list But a list can hold anything…

  18. Scheme (cons ’1 ’(3 4 5 7)) (1 3 4 5 7) Scheme (define mymap (lambda (f a b) (cond ((and (null? a) (null? b)) '()) (else (cons (f (first a) (first b)) (mymap f (first a) (first b)))))))

  19. ISWIM • Peter Landin – mid 1960s • If You See What I Mean Landon wrote “…can be looked upon as an attempt to deliver Lisp from its eponymous commitment to lists, its reputation for hand-to-mouth storage allocation, the hardware dependent flavour of its pedagogy, its heavy bracketing, and its compromises with tradition”

  20. Iswim… • Contributions • Infix syntax • let and where clauses, including a notion of simultaneous and mutually recursive definitions • the off side rule based on indentation • layout used to specify beginning and end of definitions • Emphasis on generality • small but expressive core language

  21. let in Scheme • let* - the bindings are performed sequentially (let* ((x 2) (y 3)) (let* ((x 7) (z (+ x y))) Þ ? (* z x))) (let* ((x 2) (y 3)) Þ ? (* x y))

  22. let in Scheme • let - the bindings are performed in parallel, i.e. the initial values are computed before any of the variables are bound (let ((x 2) (y 3)) (let ((x 7) (z (+ x y))) Þ ? (* z x))) (let ((x 2) (y 3)) Þ ? (* x y))

  23. letrec in Scheme • letrec – all the bindings are in effect while their initial values are being computed, allows mutually recursive definitions (letrec ((even? (lambda (n) (if (zero? n) #t (odd? (- n 1))))) (odd? (lambda (n) (if (zero? n) #f (even? (- n 1)))))) (even? 88))

  24. ML • Gordon et al 1979 • Served as the command language for a proof generating system called LCF • LCF reasoned about recursive functions • Comprised a deductive calculus and an interactive programming language – Meta Language (ML) • Has notion of references much like locations in memory • I/O – side effects • But encourages functional style of programming

  25. ML • Type System • it is strongly and statically typed • uses type inference to determine the type of every expression • allows polymorphic functions • Has user defined ADTs

  26. SASL, KRC, and Miranda add x y = + x y add 1 • Used guards • Higher Order Functions • Lazy Evaluation • Currying switch :: Int -> a -> a -> a switch n x y | n > 0 = x | otherwise = y SASL fac n = 1, n = 0 = n * fac (n-1), n>0 multiplyC :: Int -> Int -> Int Versus multiplyUC :: (Int, Int) -> Int Haskell fac n | n ==0 = 1 | n >0 = n * ( fac(n-1)

  27. SASL, KRC and Miranda • KRC introduced list comprehension • Miranda borrowed strong data typing and user defined ADTs from ML comprehension :: [Int] -> [Int] comprehension ex = [2 * n | n <- ex]

  28. COMP313AFunctional Programming (1)

  29. LISP… • McCarthy’s main contributions were • the conditional expression and its use in writing recursive functions Scheme (define fac (lambda (n) (if (= n 0) 1 (if (> n 0) (* n (fac (- n 1))) 0)))) Scheme (define fac2 (lambda (n) (cond ((= n 0) 1) ((> n 0) (* n (fac2 (- n 1)))) (else 0)))) Haskell fac ::Int -> Int fac n | n == 0 = 1 | n > 0 = fac(n-1) * n | otherwise = 0 Haskell fac :: Int -> Int fac n = if n == 0 then 1 else if n > 0 then fac(n-1) * n else 0

  30. Lisp… 2. the use of lists and higher order operations over lists such as mapcar Scheme (define mymap (lambda (f a b) (cond ((and (null? a) (null? b)) '()) (else (cons (f (first a) (first b)) (mymap f (rest a) (rest b))))))) Haskell mymap :: (Int -> Int-> Int) -> [Int] -> [Int] ->[Int] mymap f [] [] = [] mymap f (x:xs) (y:ys) = f x y : mymap f xs ys add :: Int -> Int -> Int add x y = x + y Scheme (mymap + ’(3 4 6) ’(5 7 8)) Haskell mymap add [3, 4, 6] [5, 7, 8]

  31. Lisp • cons cell and garbage collection of unused cons cells Scheme (cons ’1 ’(3 4 5 7)) (1 3 4 5 7) Haskell cons :: Int -> [Int] -> [Int] cons x xs = x:xs Scheme (define mymap (lambda (f a b) (cond ((and (null? a) (null? b)) '()) (else (cons (f (first a) (first b)) (mymap f (first a) (first b)))))))

  32. Lisp… • use of S-expressions to represent both program and data An expression is an atom or a list But a list can hold anything…

  33. Scheme (cons ’1 ’(3 4 5 7)) (1 3 4 5 7) Scheme (define mymap (lambda (f a b) (cond ((and (null? a) (null? b)) '()) (else (cons (f (first a) (first b)) (mymap f (first a) (first b)))))))

  34. ISWIM • Peter Landin – mid 1960s • If You See What I Mean Landon wrote “…can be looked upon as an attempt to deliver Lisp from its eponymous commitment to lists, its reputation for hand-to-mouth storage allocation, the hardware dependent flavour of its pedagogy, its heavy bracketing, and its compromises with tradition”

  35. Iswim… • Contributions • Infix syntax • let and where clauses, including a notion of simultaneous and mutually recursive definitions • the off side rule based on indentation • layout used to specify beginning and end of definitions • Emphasis on generality • small but expressive core language

  36. let in Scheme • let* - the bindings are performed sequentially (let* ((x 2) (y 3)) (let* ((x 7) (z (+ x y))) Þ ? (* z x))) (let* ((x 2) (y 3)) Þ ? (* x y))

  37. let in Scheme • let - the bindings are performed in parallel, i.e. the initial values are computed before any of the variables are bound (let ((x 2) (y 3)) (let ((x 7) (z (+ x y))) Þ ? (* z x))) (let ((x 2) (y 3)) Þ ? (* x y))

  38. letrec in Scheme • letrec – all the bindings are in effect while their initial values are being computed, allows mutually recursive definitions (letrec ((even? (lambda (n) (if (zero? n) #t (odd? (- n 1))))) (odd? (lambda (n) (if (zero? n) #f (even? (- n 1)))))) (even? 88))

  39. Emacs was/is written in LISP • Very popular in AI research

  40. ML • Gordon et al 1979 • Served as the command language for a proof generating system called LCF • LCF reasoned about recursive functions • Comprised a deductive calculus and an interactive programming language – Meta Language (ML) • Has notion of references much like locations in memory • I/O – side effects • But encourages functional style of programming

  41. ML • Type System • it is strongly and statically typed • uses type inference to determine the type of every expression • allows polymorphic functions • Has user defined ADTs

  42. SASL, KRC, and Miranda add x y = + x y silly_add x y = x add 4 (3 * a) • Used guards • Higher Order Functions • Lazy Evaluation • Currying switch :: Int -> a -> a -> a switch n x y | n > 0 = x | otherwise = y SASL fac n = 1, n = 0 = n * fac (n-1), n>0 multiplyC :: Int -> Int -> Int Versus multiplyUC :: (Int, Int) -> Int Haskell fac n | n ==0 = 1 | n >0 = n * fac(n-1)

  43. SASL, KRC and Miranda • KRC introduced list comprehension • Miranda borrowed strong data typing and user defined ADTs from ML comp_example :: [Int] -> [Int] comp_example ex = [2 * n | n <- ex]

  44. The Move to Haskell • Lots of functional languages in late 1970’s and 1980’s • Tower of Babel • Among these was Hope • strongly typed • polymorphism but explicit type declarations as part of all function definitions • simple module facility • user-defined concrete data types with pattern matching

  45. The Move to Haskell • 1987 – considered lack of common language was hampering the adoption of functional languages • Haskell was born • higher order functions • lazy evaluation • static polymorphic typing • user-defined datatypes • pattern matching • list comprehensions

  46. Haskell… • as well • module facility • well defined I/O system • rich set of primitive data types

  47. Higher Order Functions • Functions as first class values • stored as data structures, passed as arguments, returned as results • Function is the primary abstraction mechanism • increase the use of this abstraction • Higher order functions are the “guts” of functional programming

  48. Higher Order FunctionsComputations over lists • Mapping • add 5 to every element of a list. • add the corresponding elements of 2 lists • Filtering • Selecting the elements with a certain property • Folding • Combine the items in a list in some way

  49. List Comprehension Double all the elements in a list Using primitive recursion doubleAll :: [Int] -> [Int] doubleAll [] = [] doubleAll x:xs = 2 * x : doubleAll xs Using list comprehension doubleAll :: [Int] -> [Int] doubleAll xs :: [ 2 * x | x <- xs ]

  50. Primitive RecursionversusGeneral Recursion sum :: [Int] -> Int sum [] = 0 sum (x:xs) = x + sum xs qsort :: [Int] -> [Int] qsort [] = [] qsort (x : xs) = qsort [ y | y<-xs , y<=x] ++ [x] ++ qsort [ y | y <- xs , y>x]

More Related