| author | wenzelm | 
| Sat, 15 Apr 2023 14:44:45 +0200 | |
| changeset 77857 | 82041e01f383 | 
| parent 49863 | b5fb6e7f8d81 | 
| permissions | -rw-r--r-- | 
| 6118 | 1 | (* Title: Pure/General/seq.ML | 
| 5014 | 2 | Author: Lawrence C Paulson, Cambridge University Computer Laboratory | 
| 12851 | 3 | Author: Markus Wenzel, TU Munich | 
| 5014 | 4 | |
| 5 | Unbounded sequences implemented by closures. RECOMPUTES if sequence | |
| 6 | is re-inspected. Memoing, using polymorphic refs, was found to be | |
| 7 | slower! (More GCs) | |
| 8 | *) | |
| 9 | ||
| 10 | signature SEQ = | |
| 11 | sig | |
| 12 | type 'a seq | |
| 13 |   val make: (unit -> ('a * 'a seq) option) -> 'a seq
 | |
| 14 |   val pull: 'a seq -> ('a * 'a seq) option
 | |
| 15 | val empty: 'a seq | |
| 19475 | 16 | val cons: 'a -> 'a seq -> 'a seq | 
| 5014 | 17 | val single: 'a -> 'a seq | 
| 11721 | 18 |   val try: ('a -> 'b) -> 'a -> 'b seq
 | 
| 5014 | 19 | val hd: 'a seq -> 'a | 
| 20 | val tl: 'a seq -> 'a seq | |
| 19865 | 21 | val chop: int -> 'a seq -> 'a list * 'a seq | 
| 29857 
2cc976ed8a3c
FindTheorems: add solves feature; tidy up const name subsettin; patch by Timothy Bourke
 kleing parents: 
29606diff
changeset | 22 | val take: int -> 'a seq -> 'a seq | 
| 5014 | 23 | val list_of: 'a seq -> 'a list | 
| 24 | val of_list: 'a list -> 'a seq | |
| 19865 | 25 | val append: 'a seq -> 'a seq -> 'a seq | 
| 5014 | 26 |   val mapp: ('a -> 'b) -> 'a seq -> 'b seq -> 'b seq
 | 
| 17347 | 27 | val interleave: 'a seq * 'a seq -> 'a seq | 
| 5014 | 28 |   val filter: ('a -> bool) -> 'a seq -> 'a seq
 | 
| 29 | val flat: 'a seq seq -> 'a seq | |
| 17347 | 30 |   val map: ('a -> 'b) -> 'a seq -> 'b seq
 | 
| 31 |   val maps: ('a -> 'b seq) -> 'a seq -> 'b seq
 | |
| 19484 | 32 |   val map_filter: ('a -> 'b option) -> 'a seq -> 'b seq
 | 
| 17347 | 33 |   val lift: ('a -> 'b -> 'c) -> 'a seq -> 'b -> 'c seq
 | 
| 34 |   val lifts: ('a -> 'b -> 'c seq) -> 'a seq -> 'b -> 'c seq
 | |
| 19912 | 35 |   val singleton: ('a list -> 'b list seq) -> 'a -> 'b seq
 | 
| 5014 | 36 | val print: (int -> 'a -> unit) -> int -> 'a seq -> unit | 
| 37 |   val it_right : ('a * 'b seq -> 'b seq) -> 'a seq * 'b seq -> 'b seq
 | |
| 49859 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 38 | datatype 'a result = Result of 'a | Error of unit -> string | 
| 49863 
b5fb6e7f8d81
more informative errors for 'proof' and 'apply' steps;
 wenzelm parents: 
49859diff
changeset | 39 | val make_results: 'a seq -> 'a result seq | 
| 
b5fb6e7f8d81
more informative errors for 'proof' and 'apply' steps;
 wenzelm parents: 
49859diff
changeset | 40 | val filter_results: 'a result seq -> 'a seq | 
| 49859 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 41 |   val maps_results: ('a -> 'b result seq) -> 'a result seq -> 'b result seq
 | 
| 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 42 |   val maps_result: ('a -> 'b seq) -> 'a result seq -> 'b result seq
 | 
| 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 43 |   val map_result: ('a -> 'b) -> 'a result seq -> 'b result seq
 | 
| 49863 
b5fb6e7f8d81
more informative errors for 'proof' and 'apply' steps;
 wenzelm parents: 
49859diff
changeset | 44 | val first_result: string -> 'a result seq -> 'a * 'a seq | 
| 49859 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 45 | val the_result: string -> 'a result seq -> 'a | 
| 5014 | 46 | val succeed: 'a -> 'a seq | 
| 47 | val fail: 'a -> 'b seq | |
| 48 |   val THEN: ('a -> 'b seq) * ('b -> 'c seq) -> 'a -> 'c seq
 | |
| 49 |   val ORELSE: ('a -> 'b seq) * ('a -> 'b seq) -> 'a -> 'b seq
 | |
| 50 |   val APPEND: ('a -> 'b seq) * ('a -> 'b seq) -> 'a -> 'b seq
 | |
| 51 |   val EVERY: ('a -> 'a seq) list -> 'a -> 'a seq
 | |
| 52 |   val FIRST: ('a -> 'b seq) list -> 'a -> 'b seq
 | |
| 53 |   val TRY: ('a -> 'a seq) -> 'a -> 'a seq
 | |
| 54 |   val REPEAT: ('a -> 'a seq) -> 'a -> 'a seq
 | |
| 5558 | 55 |   val REPEAT1: ('a -> 'a seq) -> 'a -> 'a seq
 | 
| 8535 | 56 | val INTERVAL: (int -> 'a -> 'a seq) -> int -> int -> 'a -> 'a seq | 
| 12851 | 57 |   val DETERM: ('a -> 'b seq) -> 'a -> 'b seq
 | 
| 5014 | 58 | end; | 
| 59 | ||
| 60 | structure Seq: SEQ = | |
| 61 | struct | |
| 62 | ||
| 63 | ||
| 64 | (** lazy sequences **) | |
| 65 | ||
| 66 | datatype 'a seq = Seq of unit -> ('a * 'a seq) option;
 | |
| 67 | ||
| 68 | (*the abstraction for making a sequence*) | |
| 69 | val make = Seq; | |
| 70 | ||
| 15531 | 71 | (*return next sequence element as NONE or SOME (x, xq)*) | 
| 5014 | 72 | fun pull (Seq f) = f (); | 
| 73 | ||
| 74 | ||
| 75 | (*the empty sequence*) | |
| 15531 | 76 | val empty = Seq (fn () => NONE); | 
| 5014 | 77 | |
| 78 | (*prefix an element to the sequence -- use cons (x, xq) only if | |
| 79 | evaluation of xq need not be delayed, otherwise use | |
| 15531 | 80 | make (fn () => SOME (x, xq))*) | 
| 19475 | 81 | fun cons x xq = make (fn () => SOME (x, xq)); | 
| 5014 | 82 | |
| 19475 | 83 | fun single x = cons x empty; | 
| 5014 | 84 | |
| 85 | (*head and tail -- beware of calling the sequence function twice!!*) | |
| 16002 | 86 | fun hd xq = #1 (the (pull xq)) | 
| 87 | and tl xq = #2 (the (pull xq)); | |
| 5014 | 88 | |
| 11721 | 89 | (*partial function as procedure*) | 
| 90 | fun try f x = | |
| 21395 
f34ac19659ae
moved some fundamental concepts to General/basics.ML;
 wenzelm parents: 
21270diff
changeset | 91 | (case Basics.try f x of | 
| 15531 | 92 | SOME y => single y | 
| 93 | | NONE => empty); | |
| 11721 | 94 | |
| 5014 | 95 | |
| 96 | (*the list of the first n elements, paired with rest of sequence; | |
| 97 | if length of list is less than n, then sequence had less than n elements*) | |
| 19865 | 98 | fun chop n xq = | 
| 29897 | 99 | if n <= (0 : int) then ([], xq) | 
| 5014 | 100 | else | 
| 101 | (case pull xq of | |
| 15531 | 102 | NONE => ([], xq) | 
| 21395 
f34ac19659ae
moved some fundamental concepts to General/basics.ML;
 wenzelm parents: 
21270diff
changeset | 103 | | SOME (x, xq') => apfst (Basics.cons x) (chop (n - 1) xq')); | 
| 5014 | 104 | |
| 29897 | 105 | (*truncate the sequence after n elements*) | 
| 106 | fun take n xq = | |
| 107 | if n <= (0 : int) then empty | |
| 108 | else make (fn () => | |
| 109 | (Option.map o apsnd) (take (n - 1)) (pull xq)); | |
| 29857 
2cc976ed8a3c
FindTheorems: add solves feature; tidy up const name subsettin; patch by Timothy Bourke
 kleing parents: 
29606diff
changeset | 110 | |
| 5014 | 111 | (*conversion from sequence to list*) | 
| 112 | fun list_of xq = | |
| 113 | (case pull xq of | |
| 15531 | 114 | NONE => [] | 
| 115 | | SOME (x, xq') => x :: list_of xq'); | |
| 5014 | 116 | |
| 117 | (*conversion from list to sequence*) | |
| 19475 | 118 | fun of_list xs = fold_rev cons xs empty; | 
| 5014 | 119 | |
| 120 | ||
| 49859 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 121 | (*sequence append: put the elements of xq in front of those of yq*) | 
| 19865 | 122 | fun append xq yq = | 
| 17347 | 123 | let | 
| 124 | fun copy s = | |
| 125 | make (fn () => | |
| 126 | (case pull s of | |
| 127 | NONE => pull yq | |
| 128 | | SOME (x, s') => SOME (x, copy s'))) | |
| 129 | in copy xq end; | |
| 5014 | 130 | |
| 131 | (*map over a sequence xq, append the sequence yq*) | |
| 132 | fun mapp f xq yq = | |
| 133 | let | |
| 134 | fun copy s = | |
| 135 | make (fn () => | |
| 136 | (case pull s of | |
| 15531 | 137 | NONE => pull yq | 
| 138 | | SOME (x, s') => SOME (f x, copy s'))) | |
| 5014 | 139 | in copy xq end; | 
| 140 | ||
| 17347 | 141 | (*interleave elements of xq with those of yq -- fairer than append*) | 
| 142 | fun interleave (xq, yq) = | |
| 143 | make (fn () => | |
| 144 | (case pull xq of | |
| 145 | NONE => pull yq | |
| 146 | | SOME (x, xq') => SOME (x, interleave (yq, xq')))); | |
| 5014 | 147 | |
| 148 | (*filter sequence by predicate*) | |
| 149 | fun filter pred xq = | |
| 150 | let | |
| 151 | fun copy s = | |
| 152 | make (fn () => | |
| 153 | (case pull s of | |
| 15531 | 154 | NONE => NONE | 
| 155 | | SOME (x, s') => if pred x then SOME (x, copy s') else pull (copy s'))); | |
| 5014 | 156 | in copy xq end; | 
| 157 | ||
| 158 | (*flatten a sequence of sequences to a single sequence*) | |
| 159 | fun flat xqq = | |
| 160 | make (fn () => | |
| 161 | (case pull xqq of | |
| 15531 | 162 | NONE => NONE | 
| 19865 | 163 | | SOME (xq, xqq') => pull (append xq (flat xqq')))); | 
| 5014 | 164 | |
| 17347 | 165 | (*map the function f over the sequence, making a new sequence*) | 
| 166 | fun map f xq = | |
| 5014 | 167 | make (fn () => | 
| 168 | (case pull xq of | |
| 17347 | 169 | NONE => NONE | 
| 170 | | SOME (x, xq') => SOME (f x, map f xq'))); | |
| 171 | ||
| 49859 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 172 | fun maps f xq = | 
| 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 173 | make (fn () => | 
| 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 174 | (case pull xq of | 
| 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 175 | NONE => NONE | 
| 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 176 | | SOME (x, xq') => pull (append (f x) (maps f xq')))); | 
| 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 177 | |
| 19484 | 178 | fun map_filter f = maps (fn x => (case f x of NONE => empty | SOME y => single y)); | 
| 17347 | 179 | |
| 180 | fun lift f xq y = map (fn x => f x y) xq; | |
| 181 | fun lifts f xq y = maps (fn x => f x y) xq; | |
| 5014 | 182 | |
| 47060 
e2741ec9ae36
prefer explicitly qualified exception List.Empty;
 wenzelm parents: 
32195diff
changeset | 183 | fun singleton f x = f [x] |> map (fn [y] => y | _ => raise List.Empty); | 
| 19912 | 184 | |
| 16534 | 185 | (*print a sequence, up to "count" elements*) | 
| 186 | fun print print_elem count = | |
| 5014 | 187 | let | 
| 26887 | 188 | fun prnt (k: int) xq = | 
| 5014 | 189 | if k > count then () | 
| 190 | else | |
| 191 | (case pull xq of | |
| 15531 | 192 | NONE => () | 
| 16534 | 193 | | SOME (x, xq') => (print_elem k x; writeln ""; prnt (k + 1) xq')); | 
| 194 | in prnt 1 end; | |
| 5014 | 195 | |
| 196 | (*accumulating a function over a sequence; this is lazy*) | |
| 197 | fun it_right f (xq, yq) = | |
| 198 | let | |
| 199 | fun its s = | |
| 200 | make (fn () => | |
| 201 | (case pull s of | |
| 15531 | 202 | NONE => pull yq | 
| 203 | | SOME (a, s') => pull (f (a, its s')))) | |
| 5014 | 204 | in its xq end; | 
| 205 | ||
| 206 | ||
| 49859 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 207 | (* embedded errors *) | 
| 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 208 | |
| 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 209 | datatype 'a result = Result of 'a | Error of unit -> string; | 
| 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 210 | |
| 49863 
b5fb6e7f8d81
more informative errors for 'proof' and 'apply' steps;
 wenzelm parents: 
49859diff
changeset | 211 | fun make_results xq = map Result xq; | 
| 
b5fb6e7f8d81
more informative errors for 'proof' and 'apply' steps;
 wenzelm parents: 
49859diff
changeset | 212 | fun filter_results xq = map_filter (fn Result x => SOME x | Error _ => NONE) xq; | 
| 
b5fb6e7f8d81
more informative errors for 'proof' and 'apply' steps;
 wenzelm parents: 
49859diff
changeset | 213 | |
| 49859 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 214 | fun maps_results f xq = | 
| 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 215 | make (fn () => | 
| 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 216 | (case pull xq of | 
| 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 217 | NONE => NONE | 
| 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 218 | | SOME (Result x, xq') => pull (append (f x) (maps_results f xq')) | 
| 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 219 | | SOME (Error msg, xq') => SOME (Error msg, maps_results f xq'))); | 
| 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 220 | |
| 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 221 | fun maps_result f = maps_results (map Result o f); | 
| 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 222 | fun map_result f = maps_result (single o f); | 
| 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 223 | |
| 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 224 | (*first result or first error within sequence*) | 
| 49863 
b5fb6e7f8d81
more informative errors for 'proof' and 'apply' steps;
 wenzelm parents: 
49859diff
changeset | 225 | fun first_result default_msg seq = | 
| 49859 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 226 | let | 
| 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 227 | fun result opt_msg xq = | 
| 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 228 | (case (opt_msg, pull xq) of | 
| 49863 
b5fb6e7f8d81
more informative errors for 'proof' and 'apply' steps;
 wenzelm parents: 
49859diff
changeset | 229 | (_, SOME (Result x, xq')) => (x, filter_results xq') | 
| 49859 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 230 | | (SOME _, SOME (Error _, xq')) => result opt_msg xq' | 
| 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 231 | | (NONE, SOME (Error msg, xq')) => result (SOME msg) xq' | 
| 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 232 | | (SOME msg, NONE) => error (msg ()) | 
| 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 233 | | (NONE, NONE) => error (if default_msg = "" then "Empty result sequence" else default_msg)); | 
| 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 234 | in result NONE seq end; | 
| 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 235 | |
| 49863 
b5fb6e7f8d81
more informative errors for 'proof' and 'apply' steps;
 wenzelm parents: 
49859diff
changeset | 236 | fun the_result default_msg seq = #1 (first_result default_msg seq); | 
| 
b5fb6e7f8d81
more informative errors for 'proof' and 'apply' steps;
 wenzelm parents: 
49859diff
changeset | 237 | |
| 49859 
52da6a736c32
more informative error messages of initial/terminal proof methods;
 wenzelm parents: 
47060diff
changeset | 238 | |
| 5014 | 239 | |
| 32169 | 240 | (** sequence functions **) (*cf. Pure/tactical.ML*) | 
| 5014 | 241 | |
| 242 | fun succeed x = single x; | |
| 243 | fun fail _ = empty; | |
| 244 | ||
| 21270 | 245 | fun op THEN (f, g) x = maps g (f x); | 
| 5014 | 246 | |
| 5864 | 247 | fun op ORELSE (f, g) x = | 
| 5014 | 248 | (case pull (f x) of | 
| 15531 | 249 | NONE => g x | 
| 5014 | 250 | | some => make (fn () => some)); | 
| 251 | ||
| 5864 | 252 | fun op APPEND (f, g) x = | 
| 19865 | 253 | append (f x) (make (fn () => pull (g x))); | 
| 5014 | 254 | |
| 23178 | 255 | fun EVERY fs = fold_rev (curry op THEN) fs succeed; | 
| 256 | fun FIRST fs = fold_rev (curry op ORELSE) fs fail; | |
| 5014 | 257 | |
| 258 | fun TRY f = ORELSE (f, succeed); | |
| 259 | ||
| 260 | fun REPEAT f = | |
| 261 | let | |
| 262 | fun rep qs x = | |
| 263 | (case pull (f x) of | |
| 15531 | 264 | NONE => SOME (x, make (fn () => repq qs)) | 
| 265 | | SOME (x', q) => rep (q :: qs) x') | |
| 266 | and repq [] = NONE | |
| 5014 | 267 | | repq (q :: qs) = | 
| 268 | (case pull q of | |
| 15531 | 269 | NONE => repq qs | 
| 270 | | SOME (x, q) => rep (q :: qs) x); | |
| 5014 | 271 | in fn x => make (fn () => rep [] x) end; | 
| 272 | ||
| 5558 | 273 | fun REPEAT1 f = THEN (f, REPEAT f); | 
| 274 | ||
| 26887 | 275 | fun INTERVAL f (i: int) j x = | 
| 8535 | 276 | if i > j then single x | 
| 277 | else op THEN (f j, INTERVAL f i (j - 1)) x; | |
| 278 | ||
| 12851 | 279 | fun DETERM f x = | 
| 280 | (case pull (f x) of | |
| 15531 | 281 | NONE => empty | 
| 19475 | 282 | | SOME (x', _) => cons x' empty); | 
| 8535 | 283 | |
| 5014 | 284 | end; |