54 datatype 'a seq = Seq of unit -> ('a * 'a seq) option; |
54 datatype 'a seq = Seq of unit -> ('a * 'a seq) option; |
55 |
55 |
56 (*the abstraction for making a sequence*) |
56 (*the abstraction for making a sequence*) |
57 val make = Seq; |
57 val make = Seq; |
58 |
58 |
59 (*return next sequence element as None or Some (x, xq)*) |
59 (*return next sequence element as NONE or SOME (x, xq)*) |
60 fun pull (Seq f) = f (); |
60 fun pull (Seq f) = f (); |
61 |
61 |
62 |
62 |
63 (*the empty sequence*) |
63 (*the empty sequence*) |
64 val empty = Seq (fn () => None); |
64 val empty = Seq (fn () => NONE); |
65 |
65 |
66 (*prefix an element to the sequence -- use cons (x, xq) only if |
66 (*prefix an element to the sequence -- use cons (x, xq) only if |
67 evaluation of xq need not be delayed, otherwise use |
67 evaluation of xq need not be delayed, otherwise use |
68 make (fn () => Some (x, xq))*) |
68 make (fn () => SOME (x, xq))*) |
69 fun cons x_xq = make (fn () => Some x_xq); |
69 fun cons x_xq = make (fn () => SOME x_xq); |
70 |
70 |
71 fun single x = cons (x, empty); |
71 fun single x = cons (x, empty); |
72 |
72 |
73 (*head and tail -- beware of calling the sequence function twice!!*) |
73 (*head and tail -- beware of calling the sequence function twice!!*) |
74 fun hd xq = #1 (the (pull xq)) |
74 fun hd xq = #1 (the (pull xq)) |
75 and tl xq = #2 (the (pull xq)); |
75 and tl xq = #2 (the (pull xq)); |
76 |
76 |
77 (*partial function as procedure*) |
77 (*partial function as procedure*) |
78 fun try f x = |
78 fun try f x = |
79 (case Library.try f x of |
79 (case Library.try f x of |
80 Some y => single y |
80 SOME y => single y |
81 | None => empty); |
81 | NONE => empty); |
82 |
82 |
83 |
83 |
84 (*the list of the first n elements, paired with rest of sequence; |
84 (*the list of the first n elements, paired with rest of sequence; |
85 if length of list is less than n, then sequence had less than n elements*) |
85 if length of list is less than n, then sequence had less than n elements*) |
86 fun chop (n, xq) = |
86 fun chop (n, xq) = |
87 if n <= 0 then ([], xq) |
87 if n <= 0 then ([], xq) |
88 else |
88 else |
89 (case pull xq of |
89 (case pull xq of |
90 None => ([], xq) |
90 NONE => ([], xq) |
91 | Some (x, xq') => apfst (Library.cons x) (chop (n - 1, xq'))); |
91 | SOME (x, xq') => apfst (Library.cons x) (chop (n - 1, xq'))); |
92 |
92 |
93 (*conversion from sequence to list*) |
93 (*conversion from sequence to list*) |
94 fun list_of xq = |
94 fun list_of xq = |
95 (case pull xq of |
95 (case pull xq of |
96 None => [] |
96 NONE => [] |
97 | Some (x, xq') => x :: list_of xq'); |
97 | SOME (x, xq') => x :: list_of xq'); |
98 |
98 |
99 (*conversion from list to sequence*) |
99 (*conversion from list to sequence*) |
100 fun of_list xs = foldr cons (xs, empty); |
100 fun of_list xs = foldr cons (xs, empty); |
101 |
101 |
102 |
102 |
103 (*map the function f over the sequence, making a new sequence*) |
103 (*map the function f over the sequence, making a new sequence*) |
104 fun map f xq = |
104 fun map f xq = |
105 make (fn () => |
105 make (fn () => |
106 (case pull xq of |
106 (case pull xq of |
107 None => None |
107 NONE => NONE |
108 | Some (x, xq') => Some (f x, map f xq'))); |
108 | SOME (x, xq') => SOME (f x, map f xq'))); |
109 |
109 |
110 (*map over a sequence xq, append the sequence yq*) |
110 (*map over a sequence xq, append the sequence yq*) |
111 fun mapp f xq yq = |
111 fun mapp f xq yq = |
112 let |
112 let |
113 fun copy s = |
113 fun copy s = |
114 make (fn () => |
114 make (fn () => |
115 (case pull s of |
115 (case pull s of |
116 None => pull yq |
116 NONE => pull yq |
117 | Some (x, s') => Some (f x, copy s'))) |
117 | SOME (x, s') => SOME (f x, copy s'))) |
118 in copy xq end; |
118 in copy xq end; |
119 |
119 |
120 (*sequence append: put the elements of xq in front of those of yq*) |
120 (*sequence append: put the elements of xq in front of those of yq*) |
121 fun append (xq, yq) = |
121 fun append (xq, yq) = |
122 let |
122 let |
123 fun copy s = |
123 fun copy s = |
124 make (fn () => |
124 make (fn () => |
125 (case pull s of |
125 (case pull s of |
126 None => pull yq |
126 NONE => pull yq |
127 | Some (x, s') => Some (x, copy s'))) |
127 | SOME (x, s') => SOME (x, copy s'))) |
128 in copy xq end; |
128 in copy xq end; |
129 |
129 |
130 (*filter sequence by predicate*) |
130 (*filter sequence by predicate*) |
131 fun filter pred xq = |
131 fun filter pred xq = |
132 let |
132 let |
133 fun copy s = |
133 fun copy s = |
134 make (fn () => |
134 make (fn () => |
135 (case pull s of |
135 (case pull s of |
136 None => None |
136 NONE => NONE |
137 | Some (x, s') => if pred x then Some (x, copy s') else pull (copy s'))); |
137 | SOME (x, s') => if pred x then SOME (x, copy s') else pull (copy s'))); |
138 in copy xq end; |
138 in copy xq end; |
139 |
139 |
140 (*flatten a sequence of sequences to a single sequence*) |
140 (*flatten a sequence of sequences to a single sequence*) |
141 fun flat xqq = |
141 fun flat xqq = |
142 make (fn () => |
142 make (fn () => |
143 (case pull xqq of |
143 (case pull xqq of |
144 None => None |
144 NONE => NONE |
145 | Some (xq, xqq') => pull (append (xq, flat xqq')))); |
145 | SOME (xq, xqq') => pull (append (xq, flat xqq')))); |
146 |
146 |
147 (*interleave elements of xq with those of yq -- fairer than append*) |
147 (*interleave elements of xq with those of yq -- fairer than append*) |
148 fun interleave (xq, yq) = |
148 fun interleave (xq, yq) = |
149 make (fn () => |
149 make (fn () => |
150 (case pull xq of |
150 (case pull xq of |
151 None => pull yq |
151 NONE => pull yq |
152 | Some (x, xq') => Some (x, interleave (yq, xq')))); |
152 | SOME (x, xq') => SOME (x, interleave (yq, xq')))); |
153 |
153 |
154 |
154 |
155 (*functional to print a sequence, up to "count" elements; |
155 (*functional to print a sequence, up to "count" elements; |
156 the function prelem should print the element number and also the element*) |
156 the function prelem should print the element number and also the element*) |
157 fun print prelem count seq = |
157 fun print prelem count seq = |
158 let |
158 let |
159 fun pr (k, xq) = |
159 fun pr (k, xq) = |
160 if k > count then () |
160 if k > count then () |
161 else |
161 else |
162 (case pull xq of |
162 (case pull xq of |
163 None => () |
163 NONE => () |
164 | Some (x, xq') => (prelem k x; writeln ""; pr (k + 1, xq'))) |
164 | SOME (x, xq') => (prelem k x; writeln ""; pr (k + 1, xq'))) |
165 in pr (1, seq) end; |
165 in pr (1, seq) end; |
166 |
166 |
167 (*accumulating a function over a sequence; this is lazy*) |
167 (*accumulating a function over a sequence; this is lazy*) |
168 fun it_right f (xq, yq) = |
168 fun it_right f (xq, yq) = |
169 let |
169 let |
170 fun its s = |
170 fun its s = |
171 make (fn () => |
171 make (fn () => |
172 (case pull s of |
172 (case pull s of |
173 None => pull yq |
173 NONE => pull yq |
174 | Some (a, s') => pull (f (a, its s')))) |
174 | SOME (a, s') => pull (f (a, its s')))) |
175 in its xq end; |
175 in its xq end; |
176 |
176 |
177 (*turn a list of sequences into a sequence of lists*) |
177 (*turn a list of sequences into a sequence of lists*) |
178 fun commute [] = single [] |
178 fun commute [] = single [] |
179 | commute (xq :: xqs) = |
179 | commute (xq :: xqs) = |
180 make (fn () => |
180 make (fn () => |
181 (case pull xq of |
181 (case pull xq of |
182 None => None |
182 NONE => NONE |
183 | Some (x, xq') => |
183 | SOME (x, xq') => |
184 (case pull (commute xqs) of |
184 (case pull (commute xqs) of |
185 None => None |
185 NONE => NONE |
186 | Some (xs, xsq) => |
186 | SOME (xs, xsq) => |
187 Some (x :: xs, append (map (Library.cons x) xsq, commute (xq' :: xqs)))))); |
187 SOME (x :: xs, append (map (Library.cons x) xsq, commute (xq' :: xqs)))))); |
188 |
188 |
189 |
189 |
190 |
190 |
191 (** sequence functions **) (*some code copied from Pure/tctical.ML*) |
191 (** sequence functions **) (*some code copied from Pure/tctical.ML*) |
192 |
192 |