190 likes | 261 Views
Reasoning with Functional Programs. Optimization by source to source transformation Well-founded induction Streams : Infinite lists. Linear Speed-up. fun sum [] = 0 | sum (x::xs) = x + sum xs; fun double [] = [] | double (x::xs) = 2*x :: double xs;
E N D
Reasoning with Functional Programs Optimization by source to source transformation Well-founded induction Streams : Infinite lists L15strm
Linear Speed-up fun sum [] = 0 | sum (x::xs) = x + sum xs; fun double [] = [] | double (x::xs) = 2*x :: double xs; val f = sum o double; fun g [] = 0 | g (x::xs) = 2*x + g xs; L15strm
Exponential Speed-up fun fib 0 = 0 | fib 1 = 1 | fib n = fib (n-1) + fib (n-2); = #1 (g n); fun g 0 = (0,1) | g n = letval (u,v) = g (n-1) in ( v, u + v ) end; “Exponential” Fibonacci sequence definition converted into “linear” implementation. (Cf. Recursion vs Iteration debate) L15strm
Fold/Unfold Transformation Meaning preserving rules for generating new recursion equations that execute efficiently. Derivation: (* Definition (eureka) *)g(n) = (fib(n), fib(n+1)) (* Instantiation *) g(0) = (fib(0), fib(1)) (* Unfolding *) = (0,1) g(n+1) = (fib(n+1), fib(n+2)) (* Unfolding *) = (fib(n+1),fib(n)+fib(n+1) ) (* Abstraction *) = let (u,v) = g(n) in (v,u+v) end; L15strm
McCarthy’s 91-function f(x) = if x > 100 then x - 10 else f(f(x+11)) (* Determining the order on N that reflects the complexity of the function is non-trivial. *) f(0) f(f(11) ) f(f(f(22))) … f(89) f(f(100) ) f(f(f(111))) … f(90) f(f(101) ) f(91) … f(101) 91 f(102) 92 L15strm
Structuring the domain for 91-function x N : x > 100 f(x) = x - 10 x N : 89 < x <= 100 f(x) = f(f(x+11)) = f(x+11-10) = f(x+1) x N : 79 <= x <= 89 f(x) = f(f(x+11)) = f(91) = 91 Similarly for: x N : 68 <= x < 79, ... L15strm
Well-Founded Induction A relation is well-founded if there exists no infinite descending chain. … x3 x2 x1 Induction Step: if (x) for all x y, then (y) Required to show equivalences such as: f(x) = if x>100 then x-10 else f(f(x+11)) f(x) = if x>100 then x-10 else91 L15strm
Motivation for Domain Theory • Construction of Domains; Continuity A set can never be equi-numerous with its function space. However, LISP defines and represents functions in the same language. • Equivalence of Functions f1(x) = if f1(x) = 1 then 0 else 1 f2(x) = f2(x+1) f3(x) = f3(x) + 1 L15strm
Streams: Motivation Ref: SICP (Abelson and Sussman’s Structure and Interpretation of Computer Programs) L15strm
Modeling real-world objects (with state) and real-world phenomena • Use computational objects with local variables and implement time variation of states using assignments • Alternatively, use sequences to model time histories of the states of the objects. • Possible Implementations of Sequences • Using Lists • Using Streams • Delayed evaluation (demand-based evaluation) useful (necessary) when large (infinite) sequences are considered. L15strm
(define stream-car car) (define (stream-cdr s) ( (cdr s) ) ) (define (stream-cons x s) (cons x ( lambda ( ) s) ) ) (define the-empty-stream ( )) (define stream-null? null?) L15strm
(define (stream-filter p s) (cond ((stream-null? s) the-empty-stream) ((p (stream-car s)) (cons-stream (stream-car s) (stream-filter p (stream-cdr s)))) (else (stream-filter p (stream-cdr s))) ) ) (define (stream-enum-interval low high) (if (> low high) the-empty-stream (cons-stream low (stream-enum-interval (+ 1 low) high)))) L15strm
(stream-car (stream-cdr (stream-filter prime? (stream-enum-interval 100 1000)))) (define (fibgen f1 f2) (cons-stream f1 (fibgen f2 (+ f1 f2))) (define fibs (fibgen 0 1)) L15strm
Streams in ML L15strm
Infinite Lists : Streams : Lazy Lists • ML represents the tail of an infinite list by a function (thunk), to delay its evaluation. datatype ’a seq = Nil | Cons of ’a * (unit -> ’a seq) ; • The conventional termination criterion must be modified by requiring that a program generate each finite part of the result in finite time. • Tasks such as list-reversal, computing the maximum of a list, etc are no longer “computable”. L15strm
exception Empty; fun hd (Cons (x,xf)) = x | hd Nil = raise Empty; fun tl (Cons (x,xf)) = xf () | tl Nil = raise Empty; fun take (xs, 0) = [] | take (Nil,n) = raise General.Subscript | take (Cons (x,xf),n) = x:: take (xf(), n-1); L15strm
fun map f Nil = Nil | map f (Cons (x,xf)) = Cons ( f x, fn () => map f (xf ()) ); fun filter p Nil = Nil | filter p (Cons (x,xf)) = if p x thenCons (x, fn () => filter p (xf ())) elsefilter p (xf ()); fun natnum n = Cons (n, (fn () => natnum (n+1)) ); take ((map (fn i=>2*i) (natnum 0)), 10); (* val it = [0,2,4,6,8,10,12,14,16,18] : int list *) L15strm
Prime Numbers : Sieve of Eratosthenes fun sift p = filter (fn n => (n mod p) <> 0); (* eliminates numbers divisible by prime p*) fun sieve (Cons (p,nf)) = Cons( p, fn()=> sieve (sift p (nf())) ); val primes = sieve (natnum 2); take (primes, 100); (* val it = [2,3,5,7,11,13,17,19,23,29,31,37,...] : int list *) L15strm
Prime Numbers : Sieve of Eratosthenes with Lazy Evaluation nums :: Int -> [Int] nums n = n : nums (n+1) primes = sieve (nums 2) sieve (x:xs) = x : sieve [ z | z<-xs, z `mod` x /= 0] Hugs> :load I:\tkprasad\cs776\primes.hs Main> take 25 primes [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97] L15strm