mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-06 11:15:31 -05:00
updated version of Sequence
This commit is contained in:
parent
2c3af875b9
commit
37be810bbf
3 changed files with 82 additions and 21 deletions
44
sequence.ml
44
sequence.ml
|
|
@ -23,7 +23,7 @@ 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.
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*)
|
*)
|
||||||
|
|
||||||
(** {1 Transient iterators, that abstract on a finite sequence of elements. *)
|
(** {1 Transient iterators, that abstract on a finite sequence of elements.} *)
|
||||||
|
|
||||||
(** Sequence abstract iterator type *)
|
(** Sequence abstract iterator type *)
|
||||||
type 'a t = ('a -> unit) -> unit
|
type 'a t = ('a -> unit) -> unit
|
||||||
|
|
@ -36,6 +36,16 @@ type (+'a, +'b) t2 = ('a -> 'b -> unit) -> unit
|
||||||
(** Build a sequence from a iter function *)
|
(** Build a sequence from a iter function *)
|
||||||
let from_iter f = f
|
let from_iter f = f
|
||||||
|
|
||||||
|
(** Call the function repeatedly until it returns None. This
|
||||||
|
sequence is transient, use {!persistent} if needed! *)
|
||||||
|
let from_fun f =
|
||||||
|
fun k ->
|
||||||
|
let rec next () =
|
||||||
|
match f () with
|
||||||
|
| None -> ()
|
||||||
|
| Some x -> (k x; next ())
|
||||||
|
in next ()
|
||||||
|
|
||||||
let empty = fun k -> ()
|
let empty = fun k -> ()
|
||||||
|
|
||||||
let singleton x = fun k -> k x
|
let singleton x = fun k -> k x
|
||||||
|
|
@ -111,16 +121,26 @@ let concat s =
|
||||||
let k_seq seq = iter k seq in
|
let k_seq seq = iter k seq in
|
||||||
s k_seq)
|
s k_seq)
|
||||||
|
|
||||||
|
let flatten s = concat s
|
||||||
|
|
||||||
(** Monadic bind. It applies the function to every element of the
|
(** Monadic bind. It applies the function to every element of the
|
||||||
initial sequence, and calls [concat]. *)
|
initial sequence, and calls [concat]. *)
|
||||||
let flatMap f seq =
|
let flatMap f seq =
|
||||||
from_iter
|
from_iter
|
||||||
(fun k -> seq (fun x -> (f x) k))
|
(fun k -> seq (fun x -> (f x) k))
|
||||||
|
|
||||||
(** Insert the second element between every element of the sequence *)
|
let fmap f seq =
|
||||||
let intersperse seq elem =
|
|
||||||
from_iter
|
from_iter
|
||||||
(fun k -> seq (fun x -> k x; k elem))
|
(fun k ->
|
||||||
|
seq (fun x -> match f x with
|
||||||
|
| None -> ()
|
||||||
|
| Some y -> k y))
|
||||||
|
|
||||||
|
(** Insert the given element between every element of the sequence *)
|
||||||
|
let intersperse elem seq =
|
||||||
|
fun k ->
|
||||||
|
let first = ref true in
|
||||||
|
seq (fun x -> (if !first then first := false else k elem); k x)
|
||||||
|
|
||||||
(** Mutable unrolled list to serve as intermediate storage *)
|
(** Mutable unrolled list to serve as intermediate storage *)
|
||||||
module MList = struct
|
module MList = struct
|
||||||
|
|
@ -173,7 +193,9 @@ module MList = struct
|
||||||
let rec push x l =
|
let rec push x l =
|
||||||
if l.len = Array.length l.content
|
if l.len = Array.length l.content
|
||||||
then begin (* insert in the next block *)
|
then begin (* insert in the next block *)
|
||||||
(if l.tl == _empty () then l.tl <- make (Array.length l.content));
|
(if l.tl == _empty () then
|
||||||
|
let n = Array.length l.content in
|
||||||
|
l.tl <- make (n + n lsr 1));
|
||||||
push x l.tl
|
push x l.tl
|
||||||
end else begin (* insert in l *)
|
end else begin (* insert in l *)
|
||||||
l.content.(l.len) <- x;
|
l.content.(l.len) <- x;
|
||||||
|
|
@ -263,6 +285,18 @@ let product outer inner =
|
||||||
outer (fun x ->
|
outer (fun x ->
|
||||||
inner (fun y -> k (x,y))))
|
inner (fun y -> k (x,y))))
|
||||||
|
|
||||||
|
(** [join ~join_row a b] combines every element of [a] with every
|
||||||
|
element of [b] using [join_row]. If [join_row] returns None, then
|
||||||
|
the two elements do not combine. Assume that [b] allows for multiple
|
||||||
|
iterations. *)
|
||||||
|
let join ~join_row s1 s2 =
|
||||||
|
fun k ->
|
||||||
|
s1 (fun a ->
|
||||||
|
s2 (fun b ->
|
||||||
|
match join_row a b with
|
||||||
|
| None -> ()
|
||||||
|
| Some c -> k c)) (* yield the combination of [a] and [b] *)
|
||||||
|
|
||||||
(** [unfoldr f b] will apply [f] to [b]. If it
|
(** [unfoldr f b] will apply [f] to [b]. If it
|
||||||
yields [Some (x,b')] then [x] is returned
|
yields [Some (x,b')] then [x] is returned
|
||||||
and unfoldr recurses with [b']. *)
|
and unfoldr recurses with [b']. *)
|
||||||
|
|
|
||||||
55
sequence.mli
55
sequence.mli
|
|
@ -11,21 +11,32 @@ form must reproduce the above copyright notice, this list of conditions and the
|
||||||
following disclaimer in the documentation and/or other materials provided with
|
following disclaimer in the documentation and/or other materials provided with
|
||||||
the distribution.
|
the distribution.
|
||||||
|
|
||||||
this software is provided by the copyright holders and contributors "as is" and
|
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
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
warranties of merchantability and fitness for a particular purpose are
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
disclaimed. in no event shall the copyright holder or contributors be liable
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
for any direct, indirect, incidental, special, exemplary, or consequential
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
damages (including, but not limited to, procurement of substitute goods or
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
services; loss of use, data, or profits; or business interruption) however
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
caused and on any theory of liability, whether in contract, strict liability,
|
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
|
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.
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*)
|
*)
|
||||||
|
|
||||||
(** Transient iterators, that abstract on a finite sequence of elements. They
|
(** {1 Transient iterators, that abstract on a finite sequence of elements.} *)
|
||||||
are designed to allow easy transfer (mappings) between data structures,
|
|
||||||
without defining n^2 conversions between the n types. *)
|
(** The iterators are designed to allow easy transfer (mappings) between data
|
||||||
|
structures, without defining n^2 conversions between the n types. The
|
||||||
|
implementation relies on the assumption that a sequence can be iterated
|
||||||
|
on as many times as needed; this choice allows for high performance
|
||||||
|
of many combinators. However, for transient iterators, the {!persistent}
|
||||||
|
function is provided, storing elements of a transient iterator
|
||||||
|
in memory; the iterator can then be used several times.
|
||||||
|
|
||||||
|
Note that some combinators also return sequences (e.g. {!group}). The
|
||||||
|
transformation is computed on the fly every time one iterates over
|
||||||
|
the resulting sequence. If a transformation performs heavy computation,
|
||||||
|
{!persistent} can also be used as intermediate storage. *)
|
||||||
|
|
||||||
type +'a t = ('a -> unit) -> unit
|
type +'a t = ('a -> unit) -> unit
|
||||||
(** Sequence abstract iterator type, representing a finite sequence of
|
(** Sequence abstract iterator type, representing a finite sequence of
|
||||||
|
|
@ -41,6 +52,10 @@ type (+'a, +'b) t2 = ('a -> 'b -> unit) -> unit
|
||||||
val from_iter : (('a -> unit) -> unit) -> 'a t
|
val from_iter : (('a -> unit) -> unit) -> 'a t
|
||||||
(** Build a sequence from a iter function *)
|
(** Build a sequence from a iter function *)
|
||||||
|
|
||||||
|
val from_fun : (unit -> 'a option) -> 'a t
|
||||||
|
(** Call the function repeatedly until it returns None. This
|
||||||
|
sequence is transient, use {!persistent} if needed! *)
|
||||||
|
|
||||||
val empty : 'a t
|
val empty : 'a t
|
||||||
(** Empty sequence *)
|
(** Empty sequence *)
|
||||||
|
|
||||||
|
|
@ -103,11 +118,17 @@ val append : 'a t -> 'a t -> 'a t
|
||||||
val concat : 'a t t -> 'a t
|
val concat : 'a t t -> 'a t
|
||||||
(** Concatenate a sequence of sequences into one sequence *)
|
(** Concatenate a sequence of sequences into one sequence *)
|
||||||
|
|
||||||
|
val flatten : 'a t t -> 'a t
|
||||||
|
(** Alias for {!concat} *)
|
||||||
|
|
||||||
val flatMap : ('a -> 'b t) -> 'a t -> 'b t
|
val flatMap : ('a -> 'b t) -> 'a t -> 'b t
|
||||||
(** Monadic bind. It applies the function to every element of the
|
(** Monadic bind. It applies the function to every element of the
|
||||||
initial sequence, and calls [concat]. *)
|
initial sequence, and calls [concat]. *)
|
||||||
|
|
||||||
val intersperse : 'a t -> 'a -> 'a t
|
val fmap : ('a -> 'b option) -> 'a t -> 'b t
|
||||||
|
(** Specialized version of {!flatMap} for options. *)
|
||||||
|
|
||||||
|
val intersperse : 'a -> 'a t -> 'a t
|
||||||
(** Insert the second element between every element of the sequence *)
|
(** Insert the second element between every element of the sequence *)
|
||||||
|
|
||||||
val persistent : 'a t -> 'a t
|
val persistent : 'a t -> 'a t
|
||||||
|
|
@ -132,6 +153,12 @@ val product : 'a t -> 'b t -> ('a * 'b) t
|
||||||
by calling [persistent] on it, so that it can be traversed
|
by calling [persistent] on it, so that it can be traversed
|
||||||
several times (outer loop of the product) *)
|
several times (outer loop of the product) *)
|
||||||
|
|
||||||
|
val join : join_row:('a -> 'b -> 'c option) -> 'a t -> 'b t -> 'c t
|
||||||
|
(** [join ~join_row a b] combines every element of [a] with every
|
||||||
|
element of [b] using [join_row]. If [join_row] returns None, then
|
||||||
|
the two elements do not combine. Assume that [b] allows for multiple
|
||||||
|
iterations. *)
|
||||||
|
|
||||||
val unfoldr : ('b -> ('a * 'b) option) -> 'b -> 'a t
|
val unfoldr : ('b -> ('a * 'b) option) -> 'b -> 'a t
|
||||||
(** [unfoldr f b] will apply [f] to [b]. If it
|
(** [unfoldr f b] will apply [f] to [b]. If it
|
||||||
yields [Some (x,b')] then [x] is returned
|
yields [Some (x,b')] then [x] is returned
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ type 'a t
|
||||||
val empty : cmp:('a -> 'a -> int) -> 'a t
|
val empty : cmp:('a -> 'a -> int) -> 'a t
|
||||||
(** Create an empty set *)
|
(** Create an empty set *)
|
||||||
|
|
||||||
val is_empty : 'a t -> bool
|
val is_empty : _ t -> bool
|
||||||
(** Is the set empty? *)
|
(** Is the set empty? *)
|
||||||
|
|
||||||
val mem : 'a t -> 'a -> bool
|
val mem : 'a t -> 'a -> bool
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue