??
This presentation is the property of its rightful owner.
Sponsored Links
1 / 28

Programming with Streams Infinite lists v.s. Streams Normal order evaluation Recursive streams PowerPoint PPT Presentation


  • 80 Views
  • Uploaded on
  • Presentation posted in: General

??. 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.

Download Presentation

Programming with Streams Infinite lists v.s. Streams Normal order evaluation Recursive streams

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


Programming with streams infinite lists v s streams normal order evaluation recursive streams

??

  • 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


Programming with streams infinite lists v s streams normal order evaluation recursive streams

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


Programming with streams infinite lists v s streams normal order evaluation recursive streams

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


Programming with streams infinite lists v s streams normal order evaluation recursive streams

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


Programming with streams infinite lists v s streams normal order evaluation recursive streams

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


Programming with streams infinite lists v s streams normal order evaluation recursive streams

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)


  • Login