(* * Stream is a parameterized abstract type that defines a functional stream. * See 501 Lecture Notes for discussion. *) abstype ('x,'xs) stream = SNIL | Body of 'x * 'xs * ('xs->'x) * ('xs->'xs) * ('xs->bool) with (* * Exceptions Shd, Stl, and Snth are raised in precisely analogous * circumstances as Hd, Tl, and Nth are raised for lists. *) exception Shd and Stl and Snth (* * newStream is a fundamentally different constructor than list cons. * For streams, the constructor makes an initial value that is then * accessed in toto. There is incremental construction of a stream. *) fun newStream(x, xs, hdfun, tlfun, nilfun) = Body(x, xs, hdfun, tlfun, nilfun) (* * snil, snull, shd, stl, and snth are the precise analogs of their list * counterparts. *) val snil = SNIL fun snull(SNIL) = true | snull(x) = false fun shd(SNIL) = raise Shd | shd(Body(x, xs, hdfun, tlfun, nilfun)) = x:'a fun stl(SNIL) = raise Stl | stl(Body(x, xs, hdfun, tlfun, nilfun)) = if nilfun(tlfun(xs)) then snil else Body(hdfun(tlfun(xs)), tlfun(xs), hdfun, tlfun, nilfun) fun snth(s, n) = if snull(s) then raise Snth else if n = 0 then shd(s) else snth(stl(s), n-1) (* * lstream streamifies a list. *) fun lstream(l) = newStream(hd(l), l, hd, tl, null); (* * sstream streamifies a string, via a list. *) fun sstream(s) = let val es = explode(s) in newStream(hd(es), es, hd, tl, null) end (* * fstream streamifies a file for input. NOTE WELL: since ML's input * function violates referential transparency, so does stl on an fstream. * Specifically, an fstream is a call-by-var parameter to stl. This could * be prevented if ML gave us some sort of reference equality op on * instreams, or access to the instream internals. *) fun fstream(filename) = stl(newStream("",openIn(filename), fn(s)=>inputN(s,1),fn(s)=>s,endOfStream)) (* * stdIn_stream streamifies stdIn. NOTE: stl must be called first to get * it going. I.e., shd will return null on stdIn_stream until the first * stl is called. It's done this way to avoid a hang on the initial char. *) val stdIn_stream = newStream("",stdIn,fn(s)=>inputN(s,1), fn(s)=>s,endOfStream) end