Infinite Data Structures!
CS 51 and CSCI E-51 March 25, 2014
.
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
.
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
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
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
Recursion!
let rec ones = Cons(1, ones) utop[5] head ones
utop[6] head (tail ones)
utop[7] head (tail (tail ones))
3:1
Recursion!
let rec ones = Cons(1, ones) utop[5] head ones
utop[6] head (tail ones)
utop[7] head (tail (tail ones))
3:2
Recursion!
let rec ones = Cons(1, ones) utop[5] head ones
utop[6] head (tail ones)
utop[7] head (tail (tail ones))
3:3
Recursion!
let rec ones = Cons(1, ones) utop[5] head ones
utop[6] head (tail ones)
utop[7] head (tail (tail ones))
3:4
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)
4:1
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)
4:2
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)
4:3
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)
4:4
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)
4:5
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
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
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
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
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
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
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
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
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
— To Emacs —
7:1
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
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
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
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
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
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
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
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
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
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
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
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
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
— To Emacs —
11:1
(but not really) Lazy evaluation lets us delay computation until it’s needed Helps us separate concerns—decouples consumers from producers
12:1
Lazy evaluation lets us delay computation until it’s needed Helps us separate concerns—decouples consumers from producers
12:2
Helps us separate concerns—decouples consumers from producers
12:3
12:4
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
cos x =
∞
∑
i=0
(−1)i x2i (2i)! = x0 0! − x2 2! + x4 4! − x6 6! + · · ·
▶ 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
cos x =
∞
∑
i=0
(−1)i x2i (2i)! = x0 0! − x2 2! + x4 4! − x6 6! + · · ·
▶ 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
13:3