(* see: L.Allison. Continuations Implement Generators and Streams. *) (* The Computer Journal, Volume 33, Issue 5, pp460-465, 1990. *) datatype source = src of sink -> int list and sink = snk of int -> source -> int list; (* RUN is a convenience function to compose generation, processing & output *) (* ip|mid|outp *) fun RUN (src ip) mid (snk outp) = ip (snk( mid (snk( outp )) )); (* lo..hi *) fun RANGE lo hi (snk s) = if lo<=hi then s lo (src (RANGE (lo+1) hi)) else nil; (* It's convenient to leave the result in a list (but it could go to a file) *) fun PRINT n (src ins) = n :: (ins (snk PRINT)); (* ------------------------------------------------------------------------- *) (* ONEtoTWO is just a toy, example processor, ...ijk1mn... to ijk2mn... *) fun ONEtoTWO (snk outp) n (src ip) = outp (if n=1 then 2 else n) (src( fn outp2 => ip (snk(ONEtoTWO outp2)) )); (* TWICE :sink->int->source->list = sink->sink *) fun TWICE (snk outp) n (src ip) = outp n (src( fn (snk outp2) => outp2 n (src( fn outp3 => ip (snk(TWICE outp3)) ) ) ) ); (* EVEN and ODD drop every other value *) fun EVEN outp n (src ip) = ip (snk(ODD outp)) and ODD (snk outp) n (src ip) = outp n (src(fn outp2 => ip(snk(EVEN outp2)) )); (* PIPE, as in a Unix pipe *) fun PIPE CoRtn1 CoRtn2 outp n ip = CoRtn1 (snk(CoRtn2 outp)) n ip; (* CoRtn1|CoRtn2 *) (* FILTER rejects values where the predicate returns false *) fun FILTER predicate (snk outp) n (src ip) = if (predicate n)=true then outp n (src( RUN (src ip) (FILTER predicate) )) else RUN (src ip) (FILTER predicate) (snk outp); (* ------------------------------------------------------------------------- *) (* e.g. Sieve of Eratosthenes *) fun KNOT p n = not(p n); fun MULT a b = (b div a)*a=b; fun SIEVE (snk outp) n (src ip) = outp n (src( RUN (src ip) (PIPE (FILTER (KNOT(MULT n))) SIEVE) )); RUN (src(RANGE 2 100)) SIEVE (snk PRINT); (* primes = 2..100 sieve print *) (* ------------------------------------------------------------------------- *) (* examples to test the plumbing ... *) RANGE 1 10 (snk( PIPE ODD (PIPE EVEN TWICE) (snk PRINT) )); RANGE 1 10 (snk( ODD (snk(TWICE (snk(ONEtoTWO (snk PRINT) )) )) )); (* ------------------------------------------------------------------------- *) (* Program for Standard ML, SML, c1988 *) (* School of Computer SCience, Monash University, AUstralia 3168 *)