(*this is the program on PAUL, 11/14/2005 *) datatype 'a seq = Nil | Cons of 'a * (unit -> 'a seq); (* sml interpreter warns about tail, hd, and tl having patterns which do not 'cover' the domain of their parameters *) fun hd(Cons(x,_)) = x; (* type of tail is: fn: 'a seq -> 'a seq *) fun tail(Cons(_,xf)) = xf(); (* type of tl is: fn: 'a seq -> unit -> 'a seq *) fun tl(Cons(_,xf))= xf; (* need fn() to show sml interpreter that this is a function with no arguments*) fun from k = Cons(k, fn()=> from (k+1)); (* builds stream *) fun takeq (0,xq) = [] | (*enables selection of finite #*) takeq (n ,Nil) = []| (*of elements of stream*) takeq (n, Cons(x,xf)) = x::takeq(n-1, xf()); fun filtereq pred Nil = Nil | (*to filter a stream*) filtereq pred (Cons(x,xf)) = if pred x then Cons(x, fn()=>filtereq pred (xf())) else filtereq pred (xf()); (*deletes multiples of p from a sequence *) fun sift p = filtereq (fn n=> n mod p <> 0); (*repeatedly sifts a seq*) fun sieve (Cons (p,nf)) = Cons (p, fn()=>sieve (sift p (nf()))); (* this is the trace of some of the program-- rest of this is an SML comment 7 paul!programs> sml Standard ML of New Jersey, Version 0.93, February 15, 1993 val it = () : unit - use "streams2.sml"; [opening streams2.sml] [use failed: open_in "streams2.sml": openf failed, No such file or directory] - use "stream2.sml"; [opening stream2.sml] datatype 'a seq con Cons : 'a * (unit -> 'a seq) -> 'a seq con Nil : 'a seq stream2.sml:6.1-6.21 Warning: match nonexhaustive Cons (x,_) => ... val hd = fn : 'a seq -> 'a stream2.sml:8.1-8.27 Warning: match nonexhaustive Cons (_,xf) => ... val tail = fn : 'a seq -> 'a seq stream2.sml:10.1-10.22 Warning: match nonexhaustive Cons (_,xf) => ... val tl = fn : 'a seq -> unit -> 'a seq val from = fn : int -> int seq val takeq = fn : int * 'a seq -> 'a list val filtereq = fn : ('a -> bool) -> 'a seq -> 'a seq val sift = fn : int -> int seq -> int seq stream2.sml:30.1-30.63 Warning: match nonexhaustive Cons (p,nf) => ... val sieve = fn : int seq -> int seq val it = () : unit //use of these seqs encapsulated as function abstractions - val f = fn n =>(n mod 2 = 0); //setup a filter val f = fn : int -> bool - filtereq f (from 1); //have built a seq with that filter in it val it = Cons (2,fn) : int seq - tl (filtereq g (from 1)); //ask for the generator tail of that //encapsulated seq val it = fn : unit -> int seq - takeq (2,filtereq f (from 1));//how to see what is in the seq? val it = [2,4] : int list - val f = fn n =>(n mod 2 = 0); val f = fn : int -> bool - filtereq f (from 1); val it = Cons (2,fn) : int seq //note tl of the seq will give you the encapsulted seq generator function //tail of the seq tries to evaluate it -- infinite loop - tl (filtereq g (from 1)); val it = fn : unit -> int seq //to look at the seq you need to cause evaluation with takeq - takeq (2,filtereq f (from 1)); val it = [2,4] : int list - fun sift p = filtereq (fn n=> n mod p <> 0); val sift = fn : int -> int seq -> int seq - takeq (2, (sift 3) (from 1)); //1 and 2 are not multiples of 3 val it = [1,2] : int list - takeq (10, (sift 3) (from 1)); val it = [1,2,4,5,7,8,10,11,13,14] : int list //how to find out the right signature of an SML function //to know how to call it legally - sieve; val it = fn : int seq -> int seq - sieve (from 1); val it = Cons (1,fn) : int seq - sieve (from 2); val it = Cons (2,fn) : int seq - takeq (10, sieve (from 2)); //shows how sieve eliminates all multiples //of numbers that proceed others in the sequence val it = [2,3,5,7,11,13,17,19,23,29] : int list *)