1 / 57

Functional languages and how to implement them

Functional languages and how to implement them. Karl-Filip Faxén KTH/IMIT/LECS. Functional programming. A functional program computes a result from a set of arguments compute a target program from a source program compute a bitmap image from a scene description

Télécharger la présentation

Functional languages and how to implement them

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. Functional languages and how to implement them Karl-Filip Faxén KTH/IMIT/LECS

  2. Functional programming • A functional program computes a result from a set of arguments • compute a target program from a source program • compute a bitmap image from a scene description • A function (subprogram) is a function (mapping) • computes a result from arguments with • no side effects! • Well known functional languages include • Standard ML (not purely functional) • Haskell (purely functional)

  3. Functional languages • Garbage collection • Polymorphic typing • Catches all type errors at compile time • Types are inferred and need not be given • Polymorphism allows generic functions to be written • First class functions • Allows for higher order functions • Eager (strict) or lazy (nonstrict) evaluation • Standard ML is strict • Haskell is nonstrict

  4. Strict or nonstrict? let z = x/y in if y == 0 then 1 else z What happens if y=0?

  5. Strict or nonstrict? let z = x/y in if y == 0 then 1 else z What happens if y=0? - In a strict language (SML): a run-time error - In a lazy language (Haskell): return the value 1

  6. Strict or nonstrict? if y == 0 then 1 else x/y What happens if y=0?

  7. Strict or nonstrict? if y == 0 then 1 else x/y What happens if y=0? - In a strict language (SML): return the value 1 - In a lazy language (Haskell): return the value 1

  8. Data structures data List a = Nil | Cons a (List a)

  9. Data structures data List a = Nil | Cons a (List a) Defines a new type name List ...

  10. Data structures data List a = Nil | Cons a (List a) Defines a new type name List ... and two constructors, Nil and Cons.

  11. Data structures data List a = Nil | Cons a (List a) The type List is parameterized by the type parameter a which represents the type of the list elements (think of templates in C++)

  12. Data structures data List a = Nil | Cons a (List a) The constructor Nil has no arguments ...

  13. Data structures data List a = Nil | Cons a (List a) The constructor Nil has no arguments ... but the constructor Cons has two ...

  14. Data structures data List a = Nil | Cons a (List a) The constructor Nil has no arguments ... but the constructor Cons has two ... the first is a list element ...

  15. Data structures data List a = Nil | Cons a (List a) The constructor Nil has no arguments ... but the constructor Cons has two ... the first is a list element ... and the second is the rest of the list.

  16. Data structures data List a = Nil | Cons a (List a) Some examples of lists: Cons 1 (Cons 2 (Cons 3 Nil)) :: List Int Cons True (Cons False (Cons False Nil)) :: List Bool

  17. Data structures data List a = Nil | Cons a (List a) Some examples of lists: Cons 1 (Cons 2 (Cons 3 Nil)) :: List Int Cons True (Cons False (Cons False Nil)) :: List Bool The type of the list elements instantiate the type parameter of List

  18. Data structures data List a = Nil | Cons a (List a) Some examples of lists: Cons 1 (Cons 2 (Cons 3 Nil)) :: List Int Cons True (Cons False (Cons False Nil)) :: List Bool The type of the list elements instantiate the type parameter of List

  19. Computing with data structures take 0 xs = Nil take n (Cons y ys) = Cons y (take (n-1) xs) take n Nil = Nil Defines the function take; take n xs returns the first n elements of xs or xs if xs is shorter than n

  20. Computing with data structures take 0 xs = Nil take n (Cons y ys) = Cons y (take (n-1) xs) take n Nil = Nil Definition by pattern matching; a kind of implicit case statement. The first equation that matches is selected.

  21. Computing with data structures take 0 xs = Nil take n (Cons y ys) = Cons y (take (n-1) xs) take n Nil = Nil A literal pattern matches if the argument is that literal (in this case 0) ...

  22. Computing with data structures take 0 xs = Nil take n (Cons y ys) = Cons y (take (n-1) xs) take n Nil = Nil A literal pattern matches if the argument is that literal (in this case 0) ... a variable pattern matches any value (and binds the variable to it) ...

  23. Computing with data structures take 0 xs = Nil take n (Cons y ys) = Cons y (take (n-1) xs) take n Nil = Nil A literal pattern matches if the argument is that literal (in this case 0) ... a variable pattern matches any value (and binds the variable to it) ... so the first equation is chosen if the first argument is 0

  24. Computing with data structures take 0 xs = Nil take n (Cons y ys) = Cons y (take (n-1) xs) take n Nil = Nil A constructor pattern matches if ...

  25. Computing with data structures take 0 xs = Nil take n (Cons y ys) = Cons y (take (n-1) xs) take n Nil = Nil A constructor pattern matches if ... the argument is built with the same constructor ...

  26. Computing with data structures take 0 xs = Nil take n (Cons y ys) = Cons y (take (n-1) xs) take n Nil = Nil A constructor pattern matches if ... the argument is built with the same constructor ... and the component patterns match the values of the components of the argument ...

  27. Computing with data structures • take 0 xs = Nil • take n (Cons y ys) = Cons y (take (n-1) xs) • take n Nil = Nil • A constructor pattern matches if ... • the argument is built with the same constructor ... • and the component patterns match the values of the components • of the argument ... • so the second equation is chosen if • the first argument is not zero, and • the second argument is not the empty list

  28. Computing with data structures • take 0 xs = Nil • take n (Cons y ys) = Cons y (take (n-1) xs) • take n Nil = Nil • The function take is polymorphic; its type is • take :: Int -> List a -> List a • since the list elements are only extracted from and stored in • data structures

  29. Higher order functions filter p (Cons x xs) = if p(x) then Cons x (filter p xs) else filter p xs filter p Nil = Nil The parameter p is a function ...

  30. Higher order functions filter p (Cons x xs) = if p(x) then Cons x (filter p xs) else filter p xs filter p Nil = Nil The parameter p is a function ... and filter p xs returns the elements of xs for which p returns True

  31. Lazy evaluation sieve (Cons x xs) = Cons x (sieve (filter g xs)) where g y = remainder y x /= 0 from n = Cons n (from (n+1)) primes n = take n (sieve (from 2)) Compute the first n primes as the first n elements of the (infinite) list of all primes

  32. Lazy evaluation sieve (Cons x xs) = Cons x (sieve (filter g xs)) where g y = remainder y x /= 0 from n = Cons n (from (n+1)) primes n = take n (sieve (from 2)) Compute the first n primes as the first n elements of the (infinite) list of all primes

  33. Lazy evaluation sieve (Cons x xs) = Cons x (sieve (filter g xs)) where g y = remainder y x /= 0 from n = Cons n (from (n+1)) primes n = take n (sieve (from 2)) Compute the first n primes as the first n elements of the (infinite) list of all primes

  34. Representing data structures Cons descriptor Cons node Header list element next element GC info Constructor #2 Constructor # Nil 1 Cons 2 Header Value (e.g. 1) In the stack or In the heap or In the text segment in registers in the data segment

  35. Representing functions sieve (Cons x xs) = Cons x (sieve (filter g xs)) where g y = remainder y x /= 0 The function g is passed to filter; how is it represented?

  36. Representing functions sieve (Cons x xs) = Cons x (sieve (filter g xs)) where g y = remainder y x /= 0 The variable x is free in the body of g, so just a code pointer is not enough!

  37. Representing functions Function descriptor Function node Header value of x GC info Code for the body of g This pointer is passed to filter Header Value (e.g. 1)

  38. Implementing lazy evaluation from n = Cons n (from (n+1)) The function from produces its result one element at a time (Just In Time evaluation!)

  39. Implementing lazy evaluation from n = Cons n (from (n+1)) The suspended computation contains the free variable n

  40. Implementing lazy evaluation Thunk descriptor Thunk node Header value of n GC info Code for evaluating the expression from (n+1) This pointer is stored in the Cons node Header Value (e.g. 1)

  41. Implementing lazy evaluation from n = Cons n (thunk from (thunk (eval n)+1)) Thunks and evals can be made explicit in an intermediate language for lazy evaluation (Faxén -95, ...)

  42. Why lazy functional programs are (sometimes) slow • There are overheads from some features • Extra cost for building thunks which are eventually evaluated (most thunks are) • Evaluating a thunk is expensive since it involves an indirect call (bad for optimization and pipelines) • Polymorphism and GC needs uniform representations; thunks force this representation to be boxed • Difficult to make array operations efficient

  43. Why lazy functional programs are (sometimes) slow • An inefficient programming style is encouraged • Many small functions • Frequent use of higher order functions • Linked data structures rather than monolithic ones • Many intermediate data structures • But this style is good for programmers!

  44. Optimizing functional programs • Standard optimizations • Inlining, constant propagation and folding, etc • Optimizations of lazy evaluation • Strictness analysis • Cheap eagerness (Faxén -95, -00, -02) • Sharing analysis (to avoid updates) (Faxén -97) • Representation analysis (Faxén -99) • Deforestation (fusion) • Cloning (Faxén -01)

  45. Strictness analysis take 0 xs = Nil take n (Cons y ys) = Cons y (take (n-1) xs) take n Nil = Nil The function take is strict in its first argument since it is necessary to know its value in order to produce any output ...

  46. Strictness analysis take 0 xs = Nil take n (Cons y ys) = Cons y (take (n-1) xs) take n Nil = Nil The function take is strict in its first argument since it is necessary to know its value in order to produce any output ... because it is needed for pattern matching

  47. Strictness analysis take 0 xs = Nil take n (Cons y ys) = Cons y (take (n-1) xs) take n Nil = Nil The function take is not strict in its second argument since it is not necessary to know its value if the first argument is 0

  48. Cheap eagerness from n = Cons n (thunk from (thunk (eval n)+1)) primes n = take n (thunk sieve (from 2)) The function from is not strict since it can produce a Cons node without using its argument ...

  49. Cheap eagerness from n = Cons n (thunk from (thunk (eval n)+1)) primes n = take n (thunk sieve (from 2)) The function from is not strict since it can produce a Cons node without using its argument ... so the thunk can not be eliminated by strictness analysis

  50. Cheap eagerness from n = Cons n (thunk from (thunk (eval n)+1)) primes n = take n (thunk sieve (from 2)) Only the eval is expensive in the thunk body ...

More Related