??. Programming with Streams Infinite lists v.s. Streams Normal order evaluation Recursive streams Stream Diagrams Lazy patterns memoization Inductive properties of infinite lists Reading assignment Chapter 14. Programming with Streams Chapter 15. A module of reactive animations. - PowerPoint PPT Presentation
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Cse536 Functional Programming
??
• Programming with Streams– Infinite lists v.s. Streams– Normal order evaluation– Recursive streams– Stream Diagrams– Lazy patterns– memoization– Inductive properties of infinite lists
• Reading assignment– Chapter 14. Programming with Streams– Chapter 15. A module of reactive animations
•
Cse536 Functional Programming
Infinite lists v.s. Streams
data Stream a = a :^ Stream a
• A stream is an infinite list. It is never empty
• We could define a stream in Haskell as written above. But we prefer to use lists.
• This way we get to reuse all the polymorphic functions on lists.
Cse536 Functional Programming
Infinite lists and bottom
twos = 2 : twos
twos = 2 : (2 : twos)
twos = 2 : (2 : (2 : twos))
twos = 2 : (2 : (2 : (2 : twos)))
bot :: a
bot = bot
• What is the difference between twos and bot ?
Sometimes we write for bot
Cse536 Functional Programming
Normal Order evaluation
• Why does head(twos) work?– Head (2 : twos)– Head(2 : (2 : twos))– Head (2: (2 : (2 : twos)))
• The outermost – leftmost rule.• Outermost
– Use the body of the function before its arguments
• Leftmost– Use leftmost terms: (K 4) (5 + 2)– Be careful with Infix: (m + 2) `get` (x:xs)
Cse536 Functional Programming
Normal order continued
• Letlet x = y + 2
z = x / 0
in if x=0 then z else w
• Wheref w = if x=0 then z else w
where x = y + 2
z = x / 0
• Case exp’s– case f x of [] -> a ; (y:ys) -> b
Cse536 Functional Programming
Recursive streams
fibA 0 = 1
fibA 1 = 1
fibA n = fibA(n-1) + fibA(n-2)
• Unfold this a few timesfibA 8
= fibA 7 + fibA 6
= (fibA 6 + fibA 5) + (fibA 5 + fibA 4)
= ((fibA 5 + fibA 4) + (fibA 4 + fibA 3)) +((fibA 4 + fibA 3) + (fibA 3 + fibA 2))
Cse536 Functional Programming
Fibonacci Stream
fibs :: [ Integer ]
fibs = 1 : 1 : (zipWith (+) fibs (tail fibs))
This is much faster! And uses less resources. Why?
1 1 2 3 5 8 13 21 … fibonacci sequence
+ 1 2 3 5 8 13 21 34 … tail of fibonacci sequence
2 3 5 8 13 21 34 55 …tail of tail of fibonacci sequence
Cse536 Functional Programming
Abstract on tail of fibsfibs = 1 : 1 : (add fibs (tail fibs)) = 1 : tf where tf = 1 : add fibs (tail fibs) = 1 : tf where tf = 1 : add fibs tf
Abstract on tail of tf = 1 : tf where tf = 1 : tf2 tf2 = add fibs tf
server :: [Request] -> [Response]server xs = map (+1) xs
reqs = client respsresps = server reqs
Typical.A set of mutually
recursive equations
Cse536 Functional Programming
reqs = client resps = 1 : resps = 1 : server reqsAbstract on (tail reqs) = 1 : tr where tr = server reqsUse definition of server = 1 : tr where tr = 2 : server reqsabstract = 1 : tr where tr = 2 : tr2 tr2 = server reqsSince tr is used only once= 1 : 2 : tr2 where tr2 = server reqsRepeat as required
• Suppose client wants to test servers responses.clientB (y : ys) = if ok y then 1 :(y:ys) else error "faulty server" where ok x = Trueserver xs = map (+1) xs
• Now what happens . . . Reqs = client resps = client(server reqs) = client(server(client resps)) = client(server(client(server reqs))
• We can’t unfold
Cse536 Functional Programming
Solution 1
• Rewrite client
client ys = 1 : (if ok (head ys) then ys else error "faulty server") where ok x = True
• Pulling the (:) out of the if makes client immediately exhibit a cons cell
• Using (head ys) rather than the pattern (y:ys) makes the evaluation of ys lazy
Cse536 Functional Programming
Solution 2 – lazy patterns
client ~(y:ys) = 1 : (if ok y then y:ys else err) where ok x = True err = error "faulty server”
• Calculate using where clauses
Reqs = client resps = 1 : (if ok y then y:ys else err) where (y:ys) = resps = 1 : y : ys where (y:ys) = resps = 1 : resps
• But we can’t proceed since we can’t identify tf with tail(fibsFn()). Further unfolding becomes exponential.
Cse536 Functional Programming
memo1
• We need a function that builds a table of previous calls.
• Memo : (a -> b) -> (a -> b)
1 12 23 3
10
4 5
Memo fib x = if x in_Table_at i then Table[i] else set_table(x,fib x); return fib x
Memo1 builds a table with exactly 1 entry.
Cse536 Functional Programming
Using memo1
mfibsFn x =
let mfibs = memo1 mfibsFn
in 1:1:zipWith(+)(mfibs())(tail(mfibs()))
Main> take 20 (mfibsFn())
[1,1,2,3,5,8,13,21,34,55,89,144,233,377,
610,987,1597,2584,4181,6765]
Cse536 Functional Programming
Inductive properties of infinite lists
• Which properties are true of infinite lists– take n xs ++ drop n xs = xs– reverse(reverse xs) = xs
• Recall that is the error or non-terminating computation.
Think of as an approximation to an answer. We can get more precise approximations by: ones = 1 : ones
1 : 1 : 1 : 1 : 1 : 1 :
Cse536 Functional Programming
Proof by induction
• To do a proof about infinite lists, do a proof by induction where the base case is , rather than [] since an infinite list does not have a [] case (because its infinite).– 1) Prove P{}– 2) Assume P{xs} is true then prove P{x:xs}
• Auxiliary rule:– Pattern match against returns .