## CSCI 2041

### `stream`

Last time: manipulating infinite data structures in `lazyCaml`

``````let rec nats n = n::(nats (n+1))
let rec trues = true::trues``````

One way to implement these in OCaml is with a `stream` type, in which the tail of a stream is placed in a lambda expression to prevent eager evaluation:

``type 'a stream = End | Cons of 'a * (unit -> 'a stream)``
``type 'a stream  = End | Cons of 'a * (unit -> 'a stream)``

Let’s write `hd_s`, `tl_s`, `take_s`, `nat_s`, `squares_s`, `map_s`

``````let hd_s = function Cons(h,t) -> h | End -> failwith "hd_s"
let tl_s = function Cons(h,t) -> t () | End -> failwith "tl_s"``````
``````let rec take_s n s = match (n,s) with
| (0,_) | (_,End) -> []
| (_,Cons(h,t)) -> h::(take_s (n-1) (t ()))``````
``let rec nats_s n = Cons (n, fun () -> nats_s (n+1))``
``let rec squares n = Cons (n*n, fun () -> squares (n+1))``
``````let rec map_s f s = match s with
| Cons (h,t) -> Cons (f h, fun () -> map_s f (t ()))
| End -> End``````
``let rec filter_s (p : 'a -> bool) (s : 'a stream) =``
``````match s with End -> End
| Cons(h,t) -> if (p h) then Cons(h, fun () -> filter_s p (t ()))
else filter_s p (t ())``````
``````let rec sieve p =
Cons(p, fun () ->
filter_s (fun a -> a mod p <> 0) (sieve (p+1)))``````
``let rec merge (s1 : 'a stream) (s2 : 'a stream) =``
``````  match (s1,s2) with
| (End, _) -> s2
| (_, End) -> s1
| (Cons (h,t),_) -> Cons (h, fun () -> merge s2 (t ()))``````
``let rec bstrs s = Cons(s, fun () -> merge (bstrs ("0"^s)) (bstrs ("1"^s)))``

Technically, streams simulate normal order evaluation (call-by-name) but not lazy evaluation, since there is no sharing…

``````let rec natp n =
let _ = Printf.printf "evaluated natp %d\n" n in
Cons(n, fun () -> natp (n+1))

let double s = merge s s

take_s 10 (double (natp 0))``````

# `cs2041.org`

// reveal.js plugins