Infinite Data Structures! CS 51 and CSCI E-51 March 25, 2014 . - - PowerPoint PPT Presentation

infinite data structures
SMART_READER_LITE
LIVE PREVIEW

Infinite Data Structures! CS 51 and CSCI E-51 March 25, 2014 . - - PowerPoint PPT Presentation

Infinite Data Structures! CS 51 and CSCI E-51 March 25, 2014 . let head (Cons(x, _) : a stream) : a = x let tail (Cons(_, r) : a stream) : a stream = r A first attempt Consider this definition for infinite sequences: We can


slide-1
SLIDE 1

Infinite Data Structures!

CS 51 and CSCI E-51 March 25, 2014

.

slide-2
SLIDE 2

A first attempt

Consider this definition for infinite sequences:

type ’a stream = Cons of ’a * ’a stream

We can extract the head and the tail of a stream:

let head (Cons(x, _) : ’a stream) : ’a = x let tail (Cons(_, r) : ’a stream) : ’a stream = r

But how can we build one?

2:1

slide-3
SLIDE 3

A first attempt

Consider this definition for infinite sequences:

type ’a stream = Cons of ’a * ’a stream

We can extract the head and the tail of a stream:

let head (Cons(x, _) : ’a stream) : ’a = x let tail (Cons(_, r) : ’a stream) : ’a stream = r

But how can we build one?

2:2

slide-4
SLIDE 4

A first attempt

Consider this definition for infinite sequences:

type ’a stream = Cons of ’a * ’a stream

We can extract the head and the tail of a stream:

let head (Cons(x, _) : ’a stream) : ’a = x let tail (Cons(_, r) : ’a stream) : ’a stream = r

But how can we build one?

2:3

slide-5
SLIDE 5

But how can we build one?

Recursion!

let rec ones = Cons(1, ones) utop[5] head ones

  • : int = 1

utop[6] head (tail ones)

  • : int = 1

utop[7] head (tail (tail ones))

  • : int = 1

3:1

slide-6
SLIDE 6

But how can we build one?

Recursion!

let rec ones = Cons(1, ones) utop[5] head ones

  • : int = 1

utop[6] head (tail ones)

  • : int = 1

utop[7] head (tail (tail ones))

  • : int = 1

3:2

slide-7
SLIDE 7

But how can we build one?

Recursion!

let rec ones = Cons(1, ones) utop[5] head ones

  • : int = 1

utop[6] head (tail ones)

  • : int = 1

utop[7] head (tail (tail ones))

  • : int = 1

3:3

slide-8
SLIDE 8

But how can we build one?

Recursion!

let rec ones = Cons(1, ones) utop[5] head ones

  • : int = 1

utop[6] head (tail ones)

  • : int = 1

utop[7] head (tail (tail ones))

  • : int = 1

3:4

slide-9
SLIDE 9

What it means

Reduction-substitution model:

let rec ones = Cons(1, ones) let rec ones = Cons(1, let rec ones = Cons(1, ones) in ones) let rec ones = Cons(1, Cons(1, let rec ones = Cons(1, ones) in ones)) let rec ones = Cons(1, Cons(1, Cons(1, let rec ones = Cons(1, ones) in ones)))

. . . Also, this isn’t true:

utop[8]> phys_equal ones (tail ones)

  • : bool = true

4:1

slide-10
SLIDE 10

What it means

Reduction-substitution model:

let rec ones = Cons(1, ones) let rec ones = Cons(1, let rec ones = Cons(1, ones) in ones) let rec ones = Cons(1, Cons(1, let rec ones = Cons(1, ones) in ones)) let rec ones = Cons(1, Cons(1, Cons(1, let rec ones = Cons(1, ones) in ones)))

. . . Also, this isn’t true:

utop[8]> phys_equal ones (tail ones)

  • : bool = true

4:2

slide-11
SLIDE 11

What it means

Reduction-substitution model:

let rec ones = Cons(1, ones) let rec ones = Cons(1, let rec ones = Cons(1, ones) in ones) let rec ones = Cons(1, Cons(1, let rec ones = Cons(1, ones) in ones)) let rec ones = Cons(1, Cons(1, Cons(1, let rec ones = Cons(1, ones) in ones)))

. . . Also, this isn’t true:

utop[8]> phys_equal ones (tail ones)

  • : bool = true

4:3

slide-12
SLIDE 12

What it means

Reduction-substitution model:

let rec ones = Cons(1, ones) let rec ones = Cons(1, let rec ones = Cons(1, ones) in ones) let rec ones = Cons(1, Cons(1, let rec ones = Cons(1, ones) in ones)) let rec ones = Cons(1, Cons(1, Cons(1, let rec ones = Cons(1, ones) in ones)))

. . . Also, this isn’t true:

utop[8]> phys_equal ones (tail ones)

  • : bool = true

4:4

slide-13
SLIDE 13

What it means

Reduction-substitution model:

let rec ones = Cons(1, ones) let rec ones = Cons(1, let rec ones = Cons(1, ones) in ones) let rec ones = Cons(1, Cons(1, let rec ones = Cons(1, ones) in ones)) let rec ones = Cons(1, Cons(1, Cons(1, let rec ones = Cons(1, ones) in ones)))

. . . Also, this isn’t true:

utop[8]> phys_equal ones (tail ones)

  • : bool = true

4:5

slide-14
SLIDE 14

What’s really happening

let rec ones = Cons(1, ones)

.

– .– let rec onetwothrees = Cons(1, Cons(2, Cons(3, onetwothrees)))

. .

3 ..

. .

2 ..

. .1 .. How about a stream that doesn’t repeat, like the natural numbers?

5:1

slide-15
SLIDE 15

What’s really happening

let rec ones = Cons(1, ones)

. .

– .– let rec onetwothrees = Cons(1, Cons(2, Cons(3, onetwothrees)))

. .

3 ..

. .

2 ..

. .1 .. How about a stream that doesn’t repeat, like the natural numbers?

5:2

slide-16
SLIDE 16

What’s really happening

let rec ones = Cons(1, ones)

. .

1 .– let rec onetwothrees = Cons(1, Cons(2, Cons(3, onetwothrees)))

. .

3 ..

. .

2 ..

. .1 .. How about a stream that doesn’t repeat, like the natural numbers?

5:3

slide-17
SLIDE 17

What’s really happening

let rec ones = Cons(1, ones)

. .

1 ..

.

let rec onetwothrees = Cons(1, Cons(2, Cons(3, onetwothrees)))

. .

3 ..

. .

2 ..

. .1 .. How about a stream that doesn’t repeat, like the natural numbers?

5:4

slide-18
SLIDE 18

What’s really happening

let rec ones = Cons(1, ones)

. .

1 ..

.

let rec onetwothrees = Cons(1, Cons(2, Cons(3, onetwothrees)))

. .

3 ..

. .

2 ..

. .1 .. . How about a stream that doesn’t repeat, like the natural numbers?

5:5

slide-19
SLIDE 19

What’s really happening

let rec ones = Cons(1, ones)

. .

1 ..

.

let rec onetwothrees = Cons(1, Cons(2, Cons(3, onetwothrees)))

. .

3 ..

. .

2 ..

. .1 .. . How about a stream that doesn’t repeat, like the natural numbers?

5:6

slide-20
SLIDE 20

A stream of natural numbers?

let rec count_from n = Cons(n, count_from (n + 1)) let nats = count_from 0

Unfortunately, this just recurs until it blows the stack

6:1

slide-21
SLIDE 21

A stream of natural numbers?

let rec count_from n = Cons(n, count_from (n + 1)) let nats = count_from 0

Unfortunately, this just recurs until it blows the stack

6:2

slide-22
SLIDE 22

A stream of natural numbers?

let rec count_from n = Cons(n, count_from (n + 1)) let nats = count_from 0

Unfortunately, this just recurs until it blows the stack

6:3

slide-23
SLIDE 23

— To Emacs —

7:1

slide-24
SLIDE 24

Take three: memoize the thunks

type ’a promise = Unevaluated of (unit -> ’a) | Evaluated of ’a type ’a stream = ’a str promise ref and ’a str = { hd : ’a; tl : ’a stream } let rec ones = ref (Unevaluated (fun () -> { hd = 1; tl = ones })) let rec head (s : ’a stream) : ’a = match !s with | Evaluated str -> str.hd | Unevaluated f -> let str = f () in s := Evaluated str; str.hd let rec tail (s : ’a stream) : ’a stream = match !s with | Evaluated str -> str.tl | Unevaluated f -> let str = f () in s := Evaluated str; str.tl

8:1

slide-25
SLIDE 25

Take three: memoize the thunks

type ’a promise = Unevaluated of (unit -> ’a) | Evaluated of ’a type ’a stream = ’a str promise ref and ’a str = { hd : ’a; tl : ’a stream } let rec ones = ref (Unevaluated (fun () -> { hd = 1; tl = ones })) let rec head (s : ’a stream) : ’a = match !s with | Evaluated str -> str.hd | Unevaluated f -> let str = f () in s := Evaluated str; str.hd let rec tail (s : ’a stream) : ’a stream = match !s with | Evaluated str -> str.tl | Unevaluated f -> let str = f () in s := Evaluated str; str.tl

8:2

slide-26
SLIDE 26

Take three: memoize the thunks

type ’a promise = Unevaluated of (unit -> ’a) | Evaluated of ’a type ’a stream = ’a str promise ref and ’a str = { hd : ’a; tl : ’a stream } let rec ones = ref (Unevaluated (fun () -> { hd = 1; tl = ones })) let rec head (s : ’a stream) : ’a = match !s with | Evaluated str -> str.hd | Unevaluated f -> let str = f () in s := Evaluated str; str.hd let rec tail (s : ’a stream) : ’a stream = match !s with | Evaluated str -> str.tl | Unevaluated f -> let str = f () in s := Evaluated str; str.tl

8:3

slide-27
SLIDE 27

Take three: memoize the thunks

type ’a promise = Unevaluated of (unit -> ’a) | Evaluated of ’a type ’a stream = ’a str promise ref and ’a str = { hd : ’a; tl : ’a stream } let rec ones = ref (Unevaluated (fun () -> { hd = 1; tl = ones })) let rec head (s : ’a stream) : ’a = match !s with | Evaluated str -> str.hd | Unevaluated f -> let str = f () in s := Evaluated str; str.hd let rec tail (s : ’a stream) : ’a stream = match !s with | Evaluated str -> str.tl | Unevaluated f -> let str = f () in s := Evaluated str; str.tl

8:4

slide-28
SLIDE 28

Take three: memoize the thunks

type ’a promise = Unevaluated of (unit -> ’a) | Evaluated of ’a type ’a stream = ’a str promise ref and ’a str = { hd : ’a; tl : ’a stream } let rec ones = ref (Unevaluated (fun () -> { hd = 1; tl = ones })) let rec head (s : ’a stream) : ’a = match !s with | Evaluated str -> str.hd | Unevaluated f -> let str = f () in s := Evaluated str; str.hd let rec tail (s : ’a stream) : ’a stream = match !s with | Evaluated str -> str.tl | Unevaluated f -> let str = f () in s := Evaluated str; str.tl

8:5

slide-29
SLIDE 29

The laziness pattern

type ’a promise = Unevaluated of (unit -> ’a) | Evaluated of ’a type ’a my_lazy_t = ’a promise ref let force (pr : ’a my_lazy_t) : ’a = match !pr with | Evaluated v -> v | Unevaluated f -> let v = f () in pr := Evaluated v; v type ’a stream = ’a str my_lazy_t and ’a str = { hd : ’a; tl : ’a stream } let head (s : ’a stream) : ’a = (force s).hd let tail (s : ’a stream) : ’a stream = (force s).tl let rec map (s : ’a stream) ~(f : ’a -> ’b) : ’b stream = ref (Unevaluted (fun () -> { hd = f (head s); tl = map (tail s) ~f }))

9:1

slide-30
SLIDE 30

The laziness pattern

type ’a promise = Unevaluated of (unit -> ’a) | Evaluated of ’a type ’a my_lazy_t = ’a promise ref let force (pr : ’a my_lazy_t) : ’a = match !pr with | Evaluated v -> v | Unevaluated f -> let v = f () in pr := Evaluated v; v type ’a stream = ’a str my_lazy_t and ’a str = { hd : ’a; tl : ’a stream } let head (s : ’a stream) : ’a = (force s).hd let tail (s : ’a stream) : ’a stream = (force s).tl let rec map (s : ’a stream) ~(f : ’a -> ’b) : ’b stream = ref (Unevaluted (fun () -> { hd = f (head s); tl = map (tail s) ~f }))

9:2

slide-31
SLIDE 31

The laziness pattern

type ’a promise = Unevaluated of (unit -> ’a) | Evaluated of ’a type ’a my_lazy_t = ’a promise ref let force (pr : ’a my_lazy_t) : ’a = match !pr with | Evaluated v -> v | Unevaluated f -> let v = f () in pr := Evaluated v; v type ’a stream = ’a str my_lazy_t and ’a str = { hd : ’a; tl : ’a stream } let head (s : ’a stream) : ’a = (force s).hd let tail (s : ’a stream) : ’a stream = (force s).tl let rec map (s : ’a stream) ~(f : ’a -> ’b) : ’b stream = ref (Unevaluted (fun () -> { hd = f (head s); tl = map (tail s) ~f }))

9:3

slide-32
SLIDE 32

The laziness pattern

type ’a promise = Unevaluated of (unit -> ’a) | Evaluated of ’a type ’a my_lazy_t = ’a promise ref let force (pr : ’a my_lazy_t) : ’a = match !pr with | Evaluated v -> v | Unevaluated f -> let v = f () in pr := Evaluated v; v type ’a stream = ’a str my_lazy_t and ’a str = { hd : ’a; tl : ’a stream } let head (s : ’a stream) : ’a = (force s).hd let tail (s : ’a stream) : ’a stream = (force s).tl let rec map (s : ’a stream) ~(f : ’a -> ’b) : ’b stream = ref (Unevaluted (fun () -> { hd = f (head s); tl = map (tail s) ~f }))

9:4

slide-33
SLIDE 33

The laziness pattern

type ’a promise = Unevaluated of (unit -> ’a) | Evaluated of ’a type ’a my_lazy_t = ’a promise ref let force (pr : ’a my_lazy_t) : ’a = match !pr with | Evaluated v -> v | Unevaluated f -> let v = f () in pr := Evaluated v; v type ’a stream = ’a str my_lazy_t and ’a str = { hd : ’a; tl : ’a stream } let head (s : ’a stream) : ’a = (force s).hd let tail (s : ’a stream) : ’a stream = (force s).tl let rec map (s : ’a stream) ~(f : ’a -> ’b) : ’b stream = ref (Unevaluted (fun () -> { hd = f (head s); tl = map (tail s) ~f }))

9:5

slide-34
SLIDE 34

OCaml’s built-in laziness

type ’a stream = ’a str lazy_t and ’a str = { hd : ’a; tl : ’a stream } let head (s : ’a stream) : ’a = (Lazy.force s).hd let tail (s : ’a stream) : ’a stream = (Lazy.force s).tl let rec map (s : ’a stream) ~(f : ’a -> ’b) : ’b stream = lazy { hd = f (head s); tl = map (tail s) ~f }

10:1

slide-35
SLIDE 35

OCaml’s built-in laziness

type ’a stream = ’a str lazy_t and ’a str = { hd : ’a; tl : ’a stream } let head (s : ’a stream) : ’a = (Lazy.force s).hd let tail (s : ’a stream) : ’a stream = (Lazy.force s).tl let rec map (s : ’a stream) ~(f : ’a -> ’b) : ’b stream = lazy { hd = f (head s); tl = map (tail s) ~f }

10:2

slide-36
SLIDE 36

OCaml’s built-in laziness

type ’a stream = ’a str lazy_t and ’a str = { hd : ’a; tl : ’a stream } let head (s : ’a stream) : ’a = (Lazy.force s).hd let tail (s : ’a stream) : ’a stream = (Lazy.force s).tl let rec map (s : ’a stream) ~(f : ’a -> ’b) : ’b stream = lazy { hd = f (head s); tl = map (tail s) ~f }

10:3

slide-37
SLIDE 37

— To Emacs —

11:1

slide-38
SLIDE 38

The take-away

  • You can build infinite data structures

(but not really) Lazy evaluation lets us delay computation until it’s needed Helps us separate concerns—decouples consumers from producers

12:1

slide-39
SLIDE 39

The take-away

  • You can build infinite data structures (but not really)

Lazy evaluation lets us delay computation until it’s needed Helps us separate concerns—decouples consumers from producers

12:2

slide-40
SLIDE 40

The take-away

  • You can build infinite data structures (but not really)
  • Lazy evaluation lets us delay computation until it’s needed

Helps us separate concerns—decouples consumers from producers

12:3

slide-41
SLIDE 41

The take-away

  • You can build infinite data structures (but not really)
  • Lazy evaluation lets us delay computation until it’s needed
  • Helps us separate concerns—decouples consumers from producers

12:4

slide-42
SLIDE 42

(Thought) exercises

  • Other Taylor series, e.g.,

cos x =

i=0

(−1)i x2i (2i)! = x0 0! − x2 2! + x4 4! − x6 6! + · · ·

Boolean circuits as streams of booleans

The not circuit negates each value in its input stream The and and or circuits Define all of the above in terms of nand For EEs: a J-K flip-flop

How would you define infinite trees?

13:1

slide-43
SLIDE 43

(Thought) exercises

  • Other Taylor series, e.g.,

cos x =

i=0

(−1)i x2i (2i)! = x0 0! − x2 2! + x4 4! − x6 6! + · · ·

  • Boolean circuits as streams of booleans

▶ The not circuit negates each value in its input stream ▶ The and and or circuits ▶ Define all of the above in terms of nand ▶ For EEs: a J-K flip-flop

How would you define infinite trees?

13:2

slide-44
SLIDE 44

(Thought) exercises

  • Other Taylor series, e.g.,

cos x =

i=0

(−1)i x2i (2i)! = x0 0! − x2 2! + x4 4! − x6 6! + · · ·

  • Boolean circuits as streams of booleans

▶ The not circuit negates each value in its input stream ▶ The and and or circuits ▶ Define all of the above in terms of nand ▶ For EEs: a J-K flip-flop

  • How would you define infinite trees?

13:3