From 86fa8eeb8fbbdd5a4cc9f88d39675848dc19f542 Mon Sep 17 00:00:00 2001 From: Simon Cruanes Date: Mon, 31 Mar 2014 22:54:49 +0200 Subject: [PATCH] Iteratee (stoppable folds) --- _oasis | 2 +- _tags | 3 +- containers.mlpack | 3 +- containers.odocl | 3 +- iteratee.ml | 73 +++++++++++++++++++++++++++++++++++++++++++++++ iteratee.mli | 44 ++++++++++++++++++++++++++++ setup.ml | 9 +++--- 7 files changed, 129 insertions(+), 8 deletions(-) create mode 100644 iteratee.ml create mode 100644 iteratee.mli diff --git a/_oasis b/_oasis index 949e1029..db8e5428 100644 --- a/_oasis +++ b/_oasis @@ -40,7 +40,7 @@ Library "containers" Vector, Bij, PiCalculus, Bencode, Sexp, RAL, MultiSet, UnionFind, SmallSet, Leftistheap, AbsSet, CSM, MultiMap, ActionMan, BV, QCheck, BencodeOnDisk, Show, TTree, - HGraph, Automaton, Conv, Levenshtein, Bidir + HGraph, Automaton, Conv, Levenshtein, Bidir, Iteratee BuildDepends: unix Library "containers_thread" diff --git a/_tags b/_tags index 41b61360..b03b7b18 100644 --- a/_tags +++ b/_tags @@ -1,5 +1,5 @@ # OASIS_START -# DO NOT EDIT (digest: 903b251284f5204ecda731d6cf74152b) +# DO NOT EDIT (digest: fd2094ebb8dc920dfd422597f0857b18) # Ignore VCS directories, you can use the same kind of rule outside # OASIS_START/STOP if you want to exclude directories that contains # useless stuff for the build process @@ -56,6 +56,7 @@ "conv.cmx": for-pack(Containers) "levenshtein.cmx": for-pack(Containers) "bidir.cmx": for-pack(Containers) +"iteratee.cmx": for-pack(Containers) # Library containers_thread "threads/containers_thread.cmxs": use_containers_thread : package(threads) diff --git a/containers.mlpack b/containers.mlpack index 50fab8d8..02515d38 100644 --- a/containers.mlpack +++ b/containers.mlpack @@ -1,5 +1,5 @@ # OASIS_START -# DO NOT EDIT (digest: ad1a5d1dbb926223a57d547d5e717146) +# DO NOT EDIT (digest: aaae13bc67b3330cd57981dd937f5914) Cache Deque Gen @@ -41,4 +41,5 @@ Automaton Conv Levenshtein Bidir +Iteratee # OASIS_STOP diff --git a/containers.odocl b/containers.odocl index 50fab8d8..02515d38 100644 --- a/containers.odocl +++ b/containers.odocl @@ -1,5 +1,5 @@ # OASIS_START -# DO NOT EDIT (digest: ad1a5d1dbb926223a57d547d5e717146) +# DO NOT EDIT (digest: aaae13bc67b3330cd57981dd937f5914) Cache Deque Gen @@ -41,4 +41,5 @@ Automaton Conv Levenshtein Bidir +Iteratee # OASIS_STOP diff --git a/iteratee.ml b/iteratee.ml new file mode 100644 index 00000000..25fb383d --- /dev/null +++ b/iteratee.ml @@ -0,0 +1,73 @@ + +(* +copyright (c) 2013, simon cruanes +all rights reserved. + +redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. redistributions in binary +form must reproduce the above copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other materials provided with +the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*) + +type 'a t = { + fold: 'b. ('b -> 'a -> [`Continue | `Stop] * 'b) -> 'b -> 'b +} + +exception StopNow + +let of_iter i = { + fold = (fun f acc -> + let r = ref acc in + begin try i (fun x -> + let cont, acc' = f !r x in + r := acc'; + match cont with + | `Stop -> raise StopNow + | `Continue -> ()); + with StopNow -> () + end; + !r + ); +} + +let fold f acc i = + i.fold (fun acc x -> `Continue, f acc x) acc + +let iter f i = + i.fold (fun () x -> f x; `Continue, ()) () + +let map f i = { + fold=(fun g acc -> + i.fold (fun acc x -> g acc (f x)) acc + ) +} + +let of_list l = + let rec next f acc l = match l with + | [] -> acc + | x::l' -> + match f acc x with + | `Continue, acc' -> next f acc' l' + | `Stop, res -> res + in + {fold=(fun f acc -> next f acc l) } + +let to_rev_list i = + i.fold (fun acc x -> `Continue, x::acc) [] + +let to_list i = List.rev (to_rev_list i) diff --git a/iteratee.mli b/iteratee.mli new file mode 100644 index 00000000..f21843c5 --- /dev/null +++ b/iteratee.mli @@ -0,0 +1,44 @@ + +(* +copyright (c) 2013, simon cruanes +all rights reserved. + +redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. redistributions in binary +form must reproduce the above copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other materials provided with +the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*) + +(** {1 Stoppable Folds} *) + +type 'a t = { + fold: 'b. ('b -> 'a -> [`Continue | `Stop] * 'b) -> 'b -> 'b +} + +val of_iter : (('a -> unit) -> unit) -> 'a t + +val fold : ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b + +val iter : ('a -> unit) -> 'a t -> unit + +val map : ('a -> 'b) -> 'a t -> 'b t + +val of_list : 'a list -> 'a t + +val to_rev_list : 'a t -> 'a list +val to_list : 'a t -> 'a list diff --git a/setup.ml b/setup.ml index dd6377ea..eb625750 100644 --- a/setup.ml +++ b/setup.ml @@ -1,7 +1,7 @@ (* setup.ml generated for the first time by OASIS v0.3.0 *) (* OASIS_START *) -(* DO NOT EDIT (digest: 003d579056475b6add45efd6e0e9b852) *) +(* DO NOT EDIT (digest: ab136fb2303cc599d52ecdf4cdcf9067) *) (* Regenerated by OASIS v0.4.2 Visit http://oasis.forge.ocamlcore.org for more information and @@ -6903,7 +6903,8 @@ let setup_t = "Automaton"; "Conv"; "Levenshtein"; - "Bidir" + "Bidir"; + "Iteratee" ]; lib_pack = true; lib_internal_modules = []; @@ -7289,7 +7290,7 @@ let setup_t = }; oasis_fn = Some "_oasis"; oasis_version = "0.4.2"; - oasis_digest = Some "\185\132z\234t\214f\1660(}\175\179\t\218\195"; + oasis_digest = Some "[\227\135\169\022E\142\218xei\139\218Ha\163"; oasis_exec = None; oasis_setup_args = []; setup_update = false @@ -7297,6 +7298,6 @@ let setup_t = let setup () = BaseSetup.setup setup_t;; -# 7301 "setup.ml" +# 7302 "setup.ml" (* OASIS_STOP *) let () = setup ();;