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 extract the head and the tail of a stream: But how can we build one? type ’a stream = Cons of ’a * ’a stream 2:1
A first attempt Consider this definition for infinite sequences: We can extract the head and the tail of a stream: But how can we build one? type ’a stream = Cons of ’a * ’a stream let head (Cons(x, _) : ’a stream) : ’a = x let tail (Cons(_, r) : ’a stream) : ’a stream = r 2:2
A first attempt Consider this definition for infinite sequences: We can extract the head and the tail of a stream: But how can we build one? type ’a stream = Cons of ’a * ’a stream let head (Cons(x, _) : ’a stream) : ’a = x let tail (Cons(_, r) : ’a stream) : ’a stream = r 2:3
utop[5] head ones - : int = 1 utop[6] head (tail ones) - : int = 1 utop[7] head (tail (tail ones)) - : int = 1 But how can we build one? Recursion! let rec ones = Cons(1, ones) 3:1
utop[6] head (tail ones) - : int = 1 utop[7] head (tail (tail ones)) - : int = 1 But how can we build one? Recursion! let rec ones = Cons(1, ones) utop[5] head ones - : int = 1 3:2
utop[7] head (tail (tail ones)) - : int = 1 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 3:3
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
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))) utop[8]> phys_equal ones (tail ones) - : bool = true What it means Reduction-substitution model: . . . Also, this isn’t true: let rec ones = Cons(1, ones) 4:1
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))) utop[8]> phys_equal ones (tail ones) - : bool = true What it means Reduction-substitution model: . . . Also, this isn’t true: let rec ones = Cons(1, ones) let rec ones = Cons(1, let rec ones = Cons(1, ones) in ones) 4:2
let rec ones = Cons(1, Cons(1, Cons(1, let rec ones = Cons(1, ones) in ones))) utop[8]> phys_equal ones (tail ones) - : bool = true What it means Reduction-substitution model: . . . Also, this isn’t true: 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)) 4:3
utop[8]> phys_equal ones (tail ones) - : bool = true What it means Reduction-substitution model: . . . Also, this isn’t true: 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))) 4:4
What it means Reduction-substitution model: . . . Also, this isn’t true: 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))) utop[8]> phys_equal ones (tail ones) - : bool = true 4:5
– . – let rec onetwothrees = Cons(1, Cons(2, Cons(3, onetwothrees))) . 1 .. 2 .. 3 .. What’s really happening . . . . . . How about a stream that doesn’t repeat, like the natural numbers? let rec ones = Cons(1, ones) 5:1
let rec onetwothrees = Cons(1, Cons(2, Cons(3, onetwothrees))) . 1 .. 2 .. 3 .. What’s really happening . . . . . . . How about a stream that doesn’t repeat, like the natural numbers? let rec ones = Cons(1, ones) – . – 5:2
let rec onetwothrees = Cons(1, Cons(2, Cons(3, onetwothrees))) . 1 .. 2 .. 3 .. What’s really happening . . . . . . . How about a stream that doesn’t repeat, like the natural numbers? let rec ones = Cons(1, ones) 1 . – 5:3
let rec onetwothrees = Cons(1, Cons(2, Cons(3, onetwothrees))) . 1 .. 2 .. 3 .. What’s really happening How about a stream that doesn’t repeat, like the natural numbers? . . . . . . . . let rec ones = Cons(1, ones) 1 .. 5:4
What’s really happening How about a stream that doesn’t repeat, like the natural numbers? . . . . . . . . . let rec ones = Cons(1, ones) 1 .. let rec onetwothrees = Cons(1, Cons(2, Cons(3, onetwothrees))) . 1 .. 2 .. 3 .. 5:5
What’s really happening How about a stream that doesn’t repeat, like the natural numbers? . . . . . . . . . let rec ones = Cons(1, ones) 1 .. let rec onetwothrees = Cons(1, Cons(2, Cons(3, onetwothrees))) . 1 .. 2 .. 3 .. 5:6
let nats = count_from 0 A stream of natural numbers? Unfortunately, this just recurs until it blows the stack let rec count_from n = Cons(n, count_from (n + 1)) 6:1
A stream of natural numbers? Unfortunately, this just recurs until it blows the stack let rec count_from n = Cons(n, count_from (n + 1)) let nats = count_from 0 6:2
A stream of natural numbers? Unfortunately, this just recurs until it blows the stack let rec count_from n = Cons(n, count_from (n + 1)) let nats = count_from 0 6:3
— To Emacs — 7:1
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 Take three: memoize the thunks type ’a promise = Unevaluated of (unit -> ’a) | Evaluated of ’a 8:1
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 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 } 8:2
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 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 })) 8:3
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 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 8:4
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
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 })) The laziness pattern type ’a promise = Unevaluated of (unit -> ’a) | Evaluated of ’a type ’a my_lazy_t = ’a promise ref 9:1
Recommend
More recommend