-
Notifications
You must be signed in to change notification settings - Fork 1
/
Streams.sml
88 lines (82 loc) · 2.79 KB
/
Streams.sml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
signature IN_STREAM =
sig
type 'a instream
type ('a,'b) consumer = 'a instream -> ('b * 'a instream)
exception EndOfStreamException
val fromList : 'a list -> 'a instream
val read : 'a instream -> 'a * 'a instream
val readN : int * 'a instream -> ('a list) * 'a instream
val readOption : 'a instream -> ('a * 'a instream) option
val readNOption :int * 'a instream -> (('a list) * 'a instream) option
val readWhile : ('a -> bool) * 'a instream -> 'a list * 'a instream
val isEmpty : 'a instream -> bool
val process : ('a,'b) consumer * 'a instream -> 'b list
end
signature OUT_STREAM =
sig
type 'a outstream
exception StreamOverflowException
val toList : 'a outstream -> 'a list
val write : 'a * 'a outstream -> 'a outstream
val writeList : 'a list * 'a outstream -> 'a outstream
val empty : 'a outstream
end
signature STREAMS =
sig
type 'a instream
type 'a outstream
val toOutstream : 'a instream -> 'a outstream
val toInstream : 'a outstream -> 'a instream
val copyTo : 'a instream -> 'a outstream -> 'a outstream
end
structure ListInstream : IN_STREAM =
struct
type 'a instream = 'a list
type ('a,'b) consumer = 'a instream -> ('b * 'a instream)
exception EndOfStreamException
fun fromList x = x
fun read [] = raise EndOfStreamException
| read (x::xs) = (x,xs)
fun readOption x = SOME(read x) handle EndOfStreamException => NONE
fun readNInner (ls,0,stream) = (rev ls,stream)
| readNInner (_,_,[]) = raise EndOfStreamException
| readNInner (ls,n,x::rest) = readNInner(x::ls,n-1,rest)
fun readN (n,stream) = readNInner ([],n,stream)
fun readNOption x = SOME(readN x) handle EndOfStreamException => NONE
fun readWhileInner(ls,_,[]) = (rev ls,[])
| readWhileInner(ls,p,x::xs) = case p(x) of
true => readWhileInner(x::ls,p,xs)
| false => (rev ls,x::xs)
fun readWhile (p,s) = readWhileInner([],p,s)
fun isEmpty [] = true
| isEmpty _ = false
fun processAcc(acc,f,[]) = rev acc
| processAcc(acc,f, str) =
let val (x,xs) = f(str) in
processAcc(x::acc,f,xs)
end
fun process(f,str) = processAcc([],f,str)
end
structure ListOutstream : OUT_STREAM =
struct
type 'a outstream = 'a list
exception StreamOverflowException
val empty = []
fun write (x,xs) = x::xs
fun writeList ([],xs) = xs
| writeList (x::xs, rest) = writeList(xs,write(x,rest))
fun toList x = rev x
end
functor Streams(structure InS:IN_STREAM
structure OutS:OUT_STREAM):STREAMS =
struct
type 'a instream = 'a InS.instream
type 'a outstream = 'a OutS.outstream
fun toInstream x = InS.fromList(OutS.toList x)
fun copyTo source dest = let val (x,xs) = InS.read source in
copyTo xs (OutS.write(x,dest))
end handle EndOfStreamException => dest
fun toOutstream x = copyTo x (OutS.empty)
end
structure ListStreams = Streams(structure InS = ListInstream
structure OutS = ListOutstream);