lecture 14 nov 10 2004 n.
Download
Skip this Video
Download Presentation
Lecture #14, Nov. 10, 2004

Loading in 2 Seconds...

play fullscreen
1 / 28

Lecture #14, Nov. 10, 2004 - PowerPoint PPT Presentation


  • 97 Views
  • Uploaded on

Lecture #14, Nov. 10, 2004. 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

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about 'Lecture #14, Nov. 10, 2004' - francine-richard


Download Now 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.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
lecture 14 nov 10 2004
Lecture #14, Nov. 10, 2004
  • 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
infinite lists v s streams
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.
infinite lists and bottom
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 z for bot

normal order evaluation
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)
normal order continued
Normal order continued
  • Let

let x = y + 2

z = x / 0

in if x=0 then z else w

  • Where

f 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
recursive streams
Recursive streams

fibA 0 = 1

fibA 1 = 1

fibA n = fibA(n-1) + fibA(n-2)

  • Unfold this a few times

fibA 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))

fibonacci stream
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

slide8

Add x y =

zipWith (+) x y

Abstract on tail of fibs

fibs = 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

Unfold add

= 1 : tf

where tf = 1 : tf2

tf2 = 2 : add tf tf2

abstract and unfold again
Abstract and unfold again

fibs = 1 : tf

where tf = 1 : tf2

tf2 = 2 : add tf tf2

= 1 : tf

where tf = 1 : tf2

tf2 = 2 : tf3

tf3 = add tf tf2

= 1 : tf

where tf = 1 : tf2

tf2 = 2 : tf3

tf3 = 3 : add tf2 tf3

tf is used only once, so eliminate

= 1 : 1 : tf2

where tf2 = 2 : tf3

tf3 = 3 : add tf2 tf3

again
Again
  • This can go on forever. But note how the sharing makes the inefficiencies of fibA go away.

fibs = 1 : 1 : 2 : tf3

where tf3 = 3 : tf4

tf4 = 5 : add tf3 tf4

fibs = 1 : 1 : 2 : 3 : tf4

where tf4 = 5 : tf5

tf5 = 8 : add tf4 tf5

stream diagrams
Stream Diagrams

fibs = [1,1,2,3,5,8,…]

  • Streams are “wires” along
  • which values flow.
  • Boxes and circles take
  • wires as input and produce
  • values for new wires as
  • output.
  • Forks in a wire send their
  • values to both destinations
  • A stream diagram corresponds
  • to a Haskell function (usually
  • recursive)

(:)

[1,2,3,5,8, …]

1

(:)

[2,3,5,8,…]

1

add

example stream diagram

[0]

+1

if*

next

out

0

inp

Example Stream Diagram

counter :: [ Bool ] -> [ Int ]

counter inp = out

where

out = if* inp then* 0 else* next

next = [0] followedBy map (+ 1) out

slide13

1...

[0]

0...

+1

if*

0...

next

out

0

F...

Example

counter :: [ Bool ] -> [ Int ]

counter inp = out

where

out = if* inp then* 0 else* next

next = [0] followedBy map (+ 1) out

slide14

1:2..

[0]

0:1..

+1

if*

0:1..

next

out

0

F:F..

Example

counter :: [ Bool ] -> [ Int ]

counter inp = out

where

out = if* inp then* 0 else* next

next = [0] followedBy map (+ 1) out

slide15

1:2:1..

[0]

0:1:2

+1

if*

0:1:0..

next

out

0

F:F:T..

Example

counter :: [ Bool ] -> [ Int ]

counter inp = out

where

out = if* inp then* 0 else* next

next = [0] followedBy map (+ 1) out

client server example
Client, Server Example

type Response = Integer

type Request = Integer

client :: [Response] -> [Request]

client ys = 1 : ys

server :: [Request] -> [Response]

server xs = map (+1) xs

reqs = client resps

resps = server reqs

Typical.

A set of mutually

recursive equations

slide17

client ys = 1 : ys

server xs = map (+1) xs

reqs = client resps

resps = server reqs

reqs = client resps

= 1 : resps

= 1 : server reqs

Abstract on (tail reqs)

= 1 : tr

where tr = server reqs

Use definition of server

= 1 : tr

where tr = 2 : server reqs

abstract

= 1 : tr

where tr = 2 : tr2

tr2 = server reqs

Since tr is used only once

= 1 : 2 : tr2

where tr2 = server reqs

Repeat as required

lazy patterns
Lazy Patterns
  • Suppose client wants to test servers responses.

clientB (y : ys) =

if ok y

then 1 :(y:ys)

else error "faulty server"

where ok x = True

server 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
solution 1
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
solution 2 lazy patterns
Solution 2 – lazy patterns

In Haskell the ~ before a pattern makes it lazy

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

memoization
Memoization

fibsFn :: () -> [ Integer ]

fibsFn () = 1 : 1 :

(zipWith (+) (fibsFn ()) (tail (fibsFn ())))

  • Unfolding we get:

fibsFn () = 1:1: add (fibsFn()) (tail (fibsFn ()))

= 1 : tf

where tf = 1:add(fibsFn())(tail(fibsFn()))

  • But we can’t proceed since we can’t identify tf with tail(fibsFn()). Further unfolding becomes exponential.
memo1

0

1

1

1

2

2

3

3

4

5

memo1
  • We need a function that builds a table of previous calls.
  • Memo : (a -> b) -> (a -> b)

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.

using memo1
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]

inductive properties of infinite lists
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 z is the error or non-terminating computation. Think ofz as an approximation to an answer. We can get more precise approximations by: ones = 1 : ones

z

1 : z

1 : 1 : z

1 : 1 : 1 : z

proof by induction
Proof by induction
  • To do a proof about infinite lists, do a proof by induction where the base case is z, rather than [] since an infinite list does not have a [] case (because its infinite).
    • 1) Prove P{z}
    • 2) Assume P{xs} is true then prove P{x:xs}
  • Auxiliary rule:
    • Pattern match against z returns z.
      • I.e. case z of { [] -> e; y:ys -> f }
example
Example
  • Prove: P{x} ==

(x ++ y) ++ w = x ++ (y++w)

  • Prove P{z}

(z ++ y) ++ w = z ++ (y++w)

  • Assume P{xs}

(xs ++ y) ++ w = xs ++ (y++w)

Prove P{x:xs}

(x:xs ++ y) ++ w = x:xs ++ (y++w)

base case
Base Case

(z ++ y) ++ w = z ++ (y++w)

(z ++ y) ++ w

  • pattern match in def of ++

z ++ w

  • pattern match in def of ++

z

  • pattern match in def of ++

z ++ (y++w)

induction step
Induction step
  • Assume P{xs}

(xs ++ y) ++ w = xs ++ (y++w)

Prove P{x:xs}

(x:xs ++ y) ++ w = x:xs ++ (y++w)

(x:xs ++ y) ++ w

  • Def of (++)

(x:(xs ++ y)) ++ w

  • Def of (++)

x :((xs ++ y) ++ w)

  • Induction hypothesis

x : (xs ++ (y ++ w))

  • Def of (++)

(x:xs) ++ (y ++ w)