mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-06 03:05:28 -05:00
use Labels versions of CCList and CCArray
This commit is contained in:
parent
a8babbd941
commit
9b53e3c2a5
13 changed files with 884 additions and 213 deletions
2
Makefile
2
Makefile
|
|
@ -62,7 +62,7 @@ push_doc_gh: doc
|
||||||
cp -r containers.docdir/* dev/ && \
|
cp -r containers.docdir/* dev/ && \
|
||||||
git add --all dev
|
git add --all dev
|
||||||
|
|
||||||
DONTTEST=myocamlbuild.ml setup.ml $(wildcard src/**/*.cppo.*)
|
DONTTEST=myocamlbuild.ml setup.ml $(wildcard src/**/*.cppo.*) $(wildcard src/**/*Labels*)
|
||||||
QTESTABLE=$(filter-out $(DONTTEST), \
|
QTESTABLE=$(filter-out $(DONTTEST), \
|
||||||
$(wildcard src/core/*.ml) \
|
$(wildcard src/core/*.ml) \
|
||||||
$(wildcard src/core/*.mli) \
|
$(wildcard src/core/*.mli) \
|
||||||
|
|
|
||||||
1
_oasis
1
_oasis
|
|
@ -35,6 +35,7 @@ Library "containers"
|
||||||
CCFun, CCHash, CCInt, CCBool, CCFloat, CCArray, CCRef, CCSet,
|
CCFun, CCHash, CCInt, CCBool, CCFloat, CCArray, CCRef, CCSet,
|
||||||
CCOrd, CCRandom, CCString, CCHashtbl, CCMap, CCFormat, CCIO,
|
CCOrd, CCRandom, CCString, CCHashtbl, CCMap, CCFormat, CCIO,
|
||||||
CCInt64, CCChar, CCResult, CCParse, CCArray_slice,
|
CCInt64, CCChar, CCResult, CCParse, CCArray_slice,
|
||||||
|
CCListLabels, CCArrayLabels,
|
||||||
Containers
|
Containers
|
||||||
BuildDepends: bytes, result
|
BuildDepends: bytes, result
|
||||||
# BuildDepends: bytes, bisect_ppx
|
# BuildDepends: bytes, bisect_ppx
|
||||||
|
|
|
||||||
1
_tags
1
_tags
|
|
@ -159,3 +159,4 @@ true: annot, bin_annot
|
||||||
<src/data/CCFlatHashtbl.cm*> or <src/data/CCHashTrie.cm*> or <src/data/CCPersistent*>: inline(15)
|
<src/data/CCFlatHashtbl.cm*> or <src/data/CCHashTrie.cm*> or <src/data/CCPersistent*>: inline(15)
|
||||||
<src/**/*.ml> and not <src/misc/*.ml>: warn_A, warn(-4), warn(-44)
|
<src/**/*.ml> and not <src/misc/*.ml>: warn_A, warn(-4), warn(-44)
|
||||||
true: no_alias_deps, safe_string, short_paths
|
true: no_alias_deps, safe_string, short_paths
|
||||||
|
<src/**/*Labels.cm*>: nolabels
|
||||||
|
|
|
||||||
|
|
@ -22,9 +22,9 @@ type 'a t = 'a array
|
||||||
|
|
||||||
let empty = [| |]
|
let empty = [| |]
|
||||||
|
|
||||||
let map ~f a = Array.map f a
|
let map = Array.map
|
||||||
|
|
||||||
let map2 ~f a b =
|
let map2 f a b =
|
||||||
if Array.length a <> Array.length b then invalid_arg "map2";
|
if Array.length a <> Array.length b then invalid_arg "map2";
|
||||||
Array.init (Array.length a) (fun i -> f (Array.unsafe_get a i) (Array.unsafe_get b i))
|
Array.init (Array.length a) (fun i -> f (Array.unsafe_get a i) (Array.unsafe_get b i))
|
||||||
|
|
||||||
|
|
@ -49,15 +49,15 @@ let get_safe a i =
|
||||||
|
|
||||||
let set = Array.set
|
let set = Array.set
|
||||||
|
|
||||||
let fold ~f ~init a = Array.fold_left f init a
|
let fold = Array.fold_left
|
||||||
|
|
||||||
let foldi ~f ~init a =
|
let foldi f acc a =
|
||||||
let rec aux acc i =
|
let rec aux acc i =
|
||||||
if i = Array.length a then acc else aux (f acc i a.(i)) (i+1)
|
if i = Array.length a then acc else aux (f acc i a.(i)) (i+1)
|
||||||
in
|
in
|
||||||
aux init 0
|
aux acc 0
|
||||||
|
|
||||||
let fold_while ~f ~init a =
|
let fold_while f acc a =
|
||||||
let rec fold_while_i f acc i =
|
let rec fold_while_i f acc i =
|
||||||
if i < Array.length a then
|
if i < Array.length a then
|
||||||
let acc, cont = f acc a.(i) in
|
let acc, cont = f acc a.(i) in
|
||||||
|
|
@ -65,16 +65,15 @@ let fold_while ~f ~init a =
|
||||||
| `Stop -> acc
|
| `Stop -> acc
|
||||||
| `Continue -> fold_while_i f acc (i+1)
|
| `Continue -> fold_while_i f acc (i+1)
|
||||||
else acc
|
else acc
|
||||||
in fold_while_i f init 0
|
in fold_while_i f acc 0
|
||||||
|
|
||||||
(*$T
|
(*$T
|
||||||
fold_while ~f:(fun acc b -> if b then acc+1, `Continue else acc, `Stop) \
|
fold_while (fun acc b -> if b then acc+1, `Continue else acc, `Stop) 0 (Array.of_list [true;true;false;true]) = 2
|
||||||
~init:0 (Array.of_list [true;true;false;true]) = 2
|
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let iter ~f a = Array.iter f a
|
let iter = Array.iter
|
||||||
|
|
||||||
let iteri ~f a = Array.iteri f a
|
let iteri = Array.iteri
|
||||||
|
|
||||||
let blit = Array.blit
|
let blit = Array.blit
|
||||||
|
|
||||||
|
|
@ -99,53 +98,53 @@ let reverse_in_place a =
|
||||||
a = [| 6;5;4;3;2;1 |]
|
a = [| 6;5;4;3;2;1 |]
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let sorted ~f a =
|
let sorted cmp a =
|
||||||
let b = Array.copy a in
|
let b = Array.copy a in
|
||||||
Array.sort f b;
|
Array.sort cmp b;
|
||||||
b
|
b
|
||||||
|
|
||||||
(*$= & ~cmp:(=) ~printer:Q.Print.(array int)
|
(*$= & ~cmp:(=) ~printer:Q.Print.(array int)
|
||||||
[||] (sorted ~f:Pervasives.compare [||])
|
[||] (sorted Pervasives.compare [||])
|
||||||
[|0;1;2;3;4|] (sorted ~f:Pervasives.compare [|3;2;1;4;0|])
|
[|0;1;2;3;4|] (sorted Pervasives.compare [|3;2;1;4;0|])
|
||||||
*)
|
*)
|
||||||
|
|
||||||
(*$Q
|
(*$Q
|
||||||
Q.(array int) (fun a -> \
|
Q.(array int) (fun a -> \
|
||||||
let b = Array.copy a in \
|
let b = Array.copy a in \
|
||||||
Array.sort Pervasives.compare b; b = sorted ~f:Pervasives.compare a)
|
Array.sort Pervasives.compare b; b = sorted Pervasives.compare a)
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let sort_indices ~f:cmp a =
|
let sort_indices cmp a =
|
||||||
let len = Array.length a in
|
let len = Array.length a in
|
||||||
let b = Array.init len (fun k->k) in
|
let b = Array.init len (fun k->k) in
|
||||||
Array.sort (fun k1 k2 -> cmp a.(k1) a.(k2)) b;
|
Array.sort (fun k1 k2 -> cmp a.(k1) a.(k2)) b;
|
||||||
b
|
b
|
||||||
|
|
||||||
(*$= & ~cmp:(=) ~printer:Q.Print.(array int)
|
(*$= & ~cmp:(=) ~printer:Q.Print.(array int)
|
||||||
[||] (sort_indices ~f:Pervasives.compare [||])
|
[||] (sort_indices Pervasives.compare [||])
|
||||||
[|4;2;1;0;3|] (sort_indices ~f:Pervasives.compare [|"d";"c";"b";"e";"a"|])
|
[|4;2;1;0;3|] (sort_indices Pervasives.compare [|"d";"c";"b";"e";"a"|])
|
||||||
*)
|
*)
|
||||||
|
|
||||||
(*$Q
|
(*$Q
|
||||||
Q.(array printable_string) (fun a -> \
|
Q.(array printable_string) (fun a -> \
|
||||||
let b = sort_indices ~f:String.compare a in \
|
let b = sort_indices String.compare a in \
|
||||||
sorted ~f:String.compare a = map ~f:(Array.get a) b)
|
sorted String.compare a = Array.map (Array.get a) b)
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let sort_ranking ~f:cmp a =
|
let sort_ranking cmp a =
|
||||||
let cmp_int : int -> int -> int = Pervasives.compare in
|
let cmp_int : int -> int -> int = Pervasives.compare in
|
||||||
sort_indices ~f:cmp_int (sort_indices ~f:cmp a)
|
sort_indices cmp_int (sort_indices cmp a)
|
||||||
|
|
||||||
(*$= & ~cmp:(=) ~printer:Q.Print.(array int)
|
(*$= & ~cmp:(=) ~printer:Q.Print.(array int)
|
||||||
[||] (sort_ranking ~f:Pervasives.compare [||])
|
[||] (sort_ranking Pervasives.compare [||])
|
||||||
[|3;2;1;4;0|] (sort_ranking ~f:Pervasives.compare [|"d";"c";"b";"e";"a"|])
|
[|3;2;1;4;0|] (sort_ranking Pervasives.compare [|"d";"c";"b";"e";"a"|])
|
||||||
*)
|
*)
|
||||||
|
|
||||||
(*$Q
|
(*$Q
|
||||||
Q.(array printable_string) (fun a -> \
|
Q.(array printable_string) (fun a -> \
|
||||||
let b = sort_ranking ~f:String.compare a in \
|
let b = sort_ranking String.compare a in \
|
||||||
let a_sorted = sorted ~f:String.compare a in \
|
let a_sorted = sorted String.compare a in \
|
||||||
a = map ~f:(Array.get a_sorted) b)
|
a = Array.map (Array.get a_sorted) b)
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let rev a =
|
let rev a =
|
||||||
|
|
@ -169,16 +168,16 @@ let rec find_aux f a i =
|
||||||
| Some _ as res -> res
|
| Some _ as res -> res
|
||||||
| None -> find_aux f a (i+1)
|
| None -> find_aux f a (i+1)
|
||||||
|
|
||||||
let find ~f a =
|
let find f a =
|
||||||
find_aux (fun _ -> f ) a 0
|
find_aux (fun _ -> f ) a 0
|
||||||
|
|
||||||
let findi ~f a =
|
let findi f a =
|
||||||
find_aux f a 0
|
find_aux f a 0
|
||||||
|
|
||||||
let find_idx ~f a =
|
let find_idx p a =
|
||||||
find_aux (fun i x -> if f x then Some (i,x) else None) a 0
|
find_aux (fun i x -> if p x then Some (i,x) else None) a 0
|
||||||
|
|
||||||
let filter_map ~f a =
|
let filter_map f a =
|
||||||
let rec aux acc i =
|
let rec aux acc i =
|
||||||
if i = Array.length a
|
if i = Array.length a
|
||||||
then (
|
then (
|
||||||
|
|
@ -198,8 +197,8 @@ let filter_map ~f a =
|
||||||
= [| "2"; "4"; "6" |]
|
= [| "2"; "4"; "6" |]
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let filter ~f a =
|
let filter p a =
|
||||||
filter_map a ~f:(fun x -> if f x then Some x else None)
|
filter_map (fun x -> if p x then Some x else None) a
|
||||||
|
|
||||||
(* append [rev a] in front of [acc] *)
|
(* append [rev a] in front of [acc] *)
|
||||||
let rec __rev_append_list a acc i =
|
let rec __rev_append_list a acc i =
|
||||||
|
|
@ -208,7 +207,7 @@ let rec __rev_append_list a acc i =
|
||||||
else
|
else
|
||||||
__rev_append_list a (a.(i) :: acc) (i+1)
|
__rev_append_list a (a.(i) :: acc) (i+1)
|
||||||
|
|
||||||
let flat_map ~f a =
|
let flat_map f a =
|
||||||
let rec aux acc i =
|
let rec aux acc i =
|
||||||
if i = Array.length a
|
if i = Array.length a
|
||||||
then (
|
then (
|
||||||
|
|
@ -252,11 +251,11 @@ let _lookup_exn ~cmp k a i j =
|
||||||
| n when n<0 -> _lookup_rec ~cmp k a (i+1) (j-1)
|
| n when n<0 -> _lookup_rec ~cmp k a (i+1) (j-1)
|
||||||
| _ -> raise Not_found (* too high *)
|
| _ -> raise Not_found (* too high *)
|
||||||
|
|
||||||
let lookup_exn ?(cmp=Pervasives.compare) ~key a =
|
let lookup_exn ?(cmp=Pervasives.compare) k a =
|
||||||
_lookup_exn ~cmp key a 0 (Array.length a-1)
|
_lookup_exn ~cmp k a 0 (Array.length a-1)
|
||||||
|
|
||||||
let lookup ?(cmp=Pervasives.compare) ~key a =
|
let lookup ?(cmp=Pervasives.compare) k a =
|
||||||
try Some (_lookup_exn ~cmp key a 0 (Array.length a-1))
|
try Some (_lookup_exn ~cmp k a 0 (Array.length a-1))
|
||||||
with Not_found -> None
|
with Not_found -> None
|
||||||
|
|
||||||
(*$T
|
(*$T
|
||||||
|
|
@ -269,20 +268,20 @@ let lookup ?(cmp=Pervasives.compare) ~key a =
|
||||||
lookup 2 [| 1 |] = None
|
lookup 2 [| 1 |] = None
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let bsearch ?(cmp=Pervasives.compare) ~key a =
|
let bsearch ?(cmp=Pervasives.compare) k a =
|
||||||
let rec aux i j =
|
let rec aux i j =
|
||||||
if i > j
|
if i > j
|
||||||
then `Just_after j
|
then `Just_after j
|
||||||
else
|
else
|
||||||
let middle = i + (j - i) / 2 in (* avoid overflow *)
|
let middle = i + (j - i) / 2 in (* avoid overflow *)
|
||||||
match cmp key a.(middle) with
|
match cmp k a.(middle) with
|
||||||
| 0 -> `At middle
|
| 0 -> `At middle
|
||||||
| n when n<0 -> aux i (middle - 1)
|
| n when n<0 -> aux i (middle - 1)
|
||||||
| _ -> aux (middle + 1) j
|
| _ -> aux (middle + 1) j
|
||||||
in
|
in
|
||||||
let n = Array.length a in
|
let n = Array.length a in
|
||||||
if n=0 then `Empty
|
if n=0 then `Empty
|
||||||
else match cmp a.(0) key, cmp a.(n-1) key with
|
else match cmp a.(0) k, cmp a.(n-1) k with
|
||||||
| c, _ when c>0 -> `All_bigger
|
| c, _ when c>0 -> `All_bigger
|
||||||
| _, c when c<0 -> `All_lower
|
| _, c when c<0 -> `All_lower
|
||||||
| _ -> aux 0 (n-1)
|
| _ -> aux 0 (n-1)
|
||||||
|
|
@ -297,37 +296,37 @@ let bsearch ?(cmp=Pervasives.compare) ~key a =
|
||||||
bsearch 3 [| |] = `Empty
|
bsearch 3 [| |] = `Empty
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let (>>=) a f = flat_map ~f a
|
let (>>=) a f = flat_map f a
|
||||||
|
|
||||||
let (>>|) a f = map ~f a
|
let (>>|) a f = map f a
|
||||||
|
|
||||||
let (>|=) a f = map ~f a
|
let (>|=) a f = map f a
|
||||||
|
|
||||||
let for_all ~f a =
|
let for_all p a =
|
||||||
let rec aux i =
|
let rec aux i =
|
||||||
i = Array.length a || (f a.(i) && aux (i+1))
|
i = Array.length a || (p a.(i) && aux (i+1))
|
||||||
in
|
in
|
||||||
aux 0
|
aux 0
|
||||||
|
|
||||||
let exists ~f a =
|
let exists p a =
|
||||||
let rec aux i =
|
let rec aux i =
|
||||||
i <> Array.length a && (f a.(i) || aux (i+1))
|
i <> Array.length a && (p a.(i) || aux (i+1))
|
||||||
in
|
in
|
||||||
aux 0
|
aux 0
|
||||||
|
|
||||||
let rec _for_all2 p a1 a2 i1 i2 ~len =
|
let rec _for_all2 p a1 a2 i1 i2 ~len =
|
||||||
len=0 || (p a1.(i1) a2.(i2) && _for_all2 p a1 a2 (i1+1) (i2+1) ~len:(len-1))
|
len=0 || (p a1.(i1) a2.(i2) && _for_all2 p a1 a2 (i1+1) (i2+1) ~len:(len-1))
|
||||||
|
|
||||||
let for_all2 ~f a b =
|
let for_all2 p a b =
|
||||||
Array.length a = Array.length b
|
Array.length a = Array.length b
|
||||||
&&
|
&&
|
||||||
_for_all2 f a b 0 0 ~len:(Array.length a)
|
_for_all2 p a b 0 0 ~len:(Array.length a)
|
||||||
|
|
||||||
let rec _exists2 p a1 a2 i1 i2 ~len =
|
let rec _exists2 p a1 a2 i1 i2 ~len =
|
||||||
len>0 && (p a1.(i1) a2.(i2) || _exists2 p a1 a2 (i1+1) (i2+1) ~len:(len-1))
|
len>0 && (p a1.(i1) a2.(i2) || _exists2 p a1 a2 (i1+1) (i2+1) ~len:(len-1))
|
||||||
|
|
||||||
let exists2 ~f a b =
|
let exists2 p a b =
|
||||||
_exists2 f a b 0 0 ~len:(min (Array.length a) (Array.length b))
|
_exists2 p a b 0 0 ~len:(min (Array.length a) (Array.length b))
|
||||||
|
|
||||||
let _iter2 f a b i j ~len =
|
let _iter2 f a b i j ~len =
|
||||||
for o = 0 to len-1 do
|
for o = 0 to len-1 do
|
||||||
|
|
@ -343,13 +342,13 @@ let _fold2 f acc a b i j ~len =
|
||||||
in
|
in
|
||||||
aux acc 0
|
aux acc 0
|
||||||
|
|
||||||
let iter2 ~f a b =
|
let iter2 f a b =
|
||||||
if length a <> length b then invalid_arg "iter2";
|
if length a <> length b then invalid_arg "iter2";
|
||||||
_iter2 f a b 0 0 ~len:(Array.length a)
|
_iter2 f a b 0 0 ~len:(Array.length a)
|
||||||
|
|
||||||
let fold2 ~f ~init a b =
|
let fold2 f acc a b =
|
||||||
if length a <> length b then invalid_arg "fold2";
|
if length a <> length b then invalid_arg "fold2";
|
||||||
_fold2 f init a b 0 0 ~len:(Array.length a)
|
_fold2 f acc a b 0 0 ~len:(Array.length a)
|
||||||
|
|
||||||
let (--) i j =
|
let (--) i j =
|
||||||
if i<=j
|
if i<=j
|
||||||
|
|
@ -382,9 +381,9 @@ let (--^) i j =
|
||||||
|
|
||||||
(** all the elements of a, but the i-th, into a list *)
|
(** all the elements of a, but the i-th, into a list *)
|
||||||
let except_idx a i =
|
let except_idx a i =
|
||||||
foldi a
|
foldi
|
||||||
~f:(fun acc j elt -> if i = j then acc else elt::acc)
|
(fun acc j elt -> if i = j then acc else elt::acc)
|
||||||
~init:[]
|
[] a
|
||||||
|
|
||||||
let equal eq a b =
|
let equal eq a b =
|
||||||
let rec aux i =
|
let rec aux i =
|
||||||
|
|
@ -470,7 +469,7 @@ let pp_i ?(sep=", ") pp_item out a =
|
||||||
pp_item k out a.(k)
|
pp_item k out a.(k)
|
||||||
done
|
done
|
||||||
|
|
||||||
let to_seq a yield = iter ~f:yield a
|
let to_seq a k = iter k a
|
||||||
|
|
||||||
let to_gen a =
|
let to_gen a =
|
||||||
let k = ref 0 in
|
let k = ref 0 in
|
||||||
|
|
|
||||||
|
|
@ -31,19 +31,19 @@ val set : 'a t -> int -> 'a -> unit
|
||||||
|
|
||||||
val length : _ t -> int
|
val length : _ t -> int
|
||||||
|
|
||||||
val fold : f:('a -> 'b -> 'a) -> init:'a -> 'b t -> 'a
|
val fold : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a
|
||||||
|
|
||||||
val foldi : f:('a -> int -> 'b -> 'a) -> init:'a -> 'b t -> 'a
|
val foldi : ('a -> int -> 'b -> 'a) -> 'a -> 'b t -> 'a
|
||||||
(** Fold left on array, with index *)
|
(** Fold left on array, with index *)
|
||||||
|
|
||||||
val fold_while : f:('a -> 'b -> 'a * [`Stop | `Continue]) -> init:'a -> 'b t -> 'a
|
val fold_while : ('a -> 'b -> 'a * [`Stop | `Continue]) -> 'a -> 'b t -> 'a
|
||||||
(** Fold left on array until a stop condition via [('a, `Stop)] is
|
(** Fold left on array until a stop condition via [('a, `Stop)] is
|
||||||
indicated by the accumulator
|
indicated by the accumulator
|
||||||
@since 0.8 *)
|
@since 0.8 *)
|
||||||
|
|
||||||
val iter : f:('a -> unit) -> 'a t -> unit
|
val iter : ('a -> unit) -> 'a t -> unit
|
||||||
|
|
||||||
val iteri : f:(int -> 'a -> unit) -> 'a t -> unit
|
val iteri : (int -> 'a -> unit) -> 'a t -> unit
|
||||||
|
|
||||||
val blit : 'a t -> int -> 'a t -> int -> int -> unit
|
val blit : 'a t -> int -> 'a t -> int -> int -> unit
|
||||||
(** [blit from i into j len] copies [len] elements from the first array
|
(** [blit from i into j len] copies [len] elements from the first array
|
||||||
|
|
@ -52,18 +52,18 @@ val blit : 'a t -> int -> 'a t -> int -> int -> unit
|
||||||
val reverse_in_place : 'a t -> unit
|
val reverse_in_place : 'a t -> unit
|
||||||
(** Reverse the array in place *)
|
(** Reverse the array in place *)
|
||||||
|
|
||||||
val sorted : f:('a -> 'a -> int) -> 'a t -> 'a array
|
val sorted : ('a -> 'a -> int) -> 'a t -> 'a array
|
||||||
(** [sorted cmp a] makes a copy of [a] and sorts it with [cmp].
|
(** [sorted cmp a] makes a copy of [a] and sorts it with [cmp].
|
||||||
@since NEXT_RELEASE *)
|
@since NEXT_RELEASE *)
|
||||||
|
|
||||||
val sort_indices : f:('a -> 'a -> int) -> 'a t -> int array
|
val sort_indices : ('a -> 'a -> int) -> 'a t -> int array
|
||||||
(** [sort_indices cmp a] returns a new array [b], with the same length as [a],
|
(** [sort_indices cmp a] returns a new array [b], with the same length as [a],
|
||||||
such that [b.(i)] is the index of the [i]-th element of [a] in [sort cmp a].
|
such that [b.(i)] is the index of the [i]-th element of [a] in [sort cmp a].
|
||||||
In other words, [map (fun i -> a.(i)) (sort_indices a) = sorted cmp a].
|
In other words, [map (fun i -> a.(i)) (sort_indices a) = sorted cmp a].
|
||||||
[a] is not modified.
|
[a] is not modified.
|
||||||
@since NEXT_RELEASE *)
|
@since NEXT_RELEASE *)
|
||||||
|
|
||||||
val sort_ranking : f:('a -> 'a -> int) -> 'a t -> int array
|
val sort_ranking : ('a -> 'a -> int) -> 'a t -> int array
|
||||||
(** [sort_ranking cmp a] returns a new array [b], with the same length as [a],
|
(** [sort_ranking cmp a] returns a new array [b], with the same length as [a],
|
||||||
such that [b.(i)] is the position in [sorted cmp a] of the [i]-th
|
such that [b.(i)] is the position in [sorted cmp a] of the [i]-th
|
||||||
element of [a].
|
element of [a].
|
||||||
|
|
@ -75,31 +75,31 @@ val sort_ranking : f:('a -> 'a -> int) -> 'a t -> int array
|
||||||
[lookup_exn a.(i) (sorted a) = (sorted_ranking a).(i)]
|
[lookup_exn a.(i) (sorted a) = (sorted_ranking a).(i)]
|
||||||
@since NEXT_RELEASE *)
|
@since NEXT_RELEASE *)
|
||||||
|
|
||||||
val find : f:('a -> 'b option) -> 'a t -> 'b option
|
val find : ('a -> 'b option) -> 'a t -> 'b option
|
||||||
(** [find f a] returns [Some y] if there is an element [x] such
|
(** [find f a] returns [Some y] if there is an element [x] such
|
||||||
that [f x = Some y], else it returns [None] *)
|
that [f x = Some y], else it returns [None] *)
|
||||||
|
|
||||||
val findi : f:(int -> 'a -> 'b option) -> 'a t -> 'b option
|
val findi : (int -> 'a -> 'b option) -> 'a t -> 'b option
|
||||||
(** Like {!find}, but also pass the index to the predicate function.
|
(** Like {!find}, but also pass the index to the predicate function.
|
||||||
@since 0.3.4 *)
|
@since 0.3.4 *)
|
||||||
|
|
||||||
val find_idx : f:('a -> bool) -> 'a t -> (int * 'a) option
|
val find_idx : ('a -> bool) -> 'a t -> (int * 'a) option
|
||||||
(** [find_idx p x] returns [Some (i,x)] where [x] is the [i]-th element of [l],
|
(** [find_idx p x] returns [Some (i,x)] where [x] is the [i]-th element of [l],
|
||||||
and [p x] holds. Otherwise returns [None]
|
and [p x] holds. Otherwise returns [None]
|
||||||
@since 0.3.4 *)
|
@since 0.3.4 *)
|
||||||
|
|
||||||
val lookup : ?cmp:'a ord -> key:'a -> 'a t -> int option
|
val lookup : ?cmp:'a ord -> 'a -> 'a t -> int option
|
||||||
(** Lookup the index of some value in a sorted array.
|
(** Lookup the index of some value in a sorted array.
|
||||||
@return [None] if the key is not present, or
|
@return [None] if the key is not present, or
|
||||||
[Some i] ([i] the index of the key) otherwise *)
|
[Some i] ([i] the index of the key) otherwise *)
|
||||||
|
|
||||||
val lookup_exn : ?cmp:'a ord -> key:'a -> 'a t -> int
|
val lookup_exn : ?cmp:'a ord -> 'a -> 'a t -> int
|
||||||
(** Same as {!lookup_exn}, but
|
(** Same as {!lookup_exn}, but
|
||||||
@raise Not_found if the key is not present *)
|
@raise Not_found if the key is not present *)
|
||||||
|
|
||||||
val bsearch : ?cmp:('a -> 'a -> int) -> key:'a -> 'a t ->
|
val bsearch : ?cmp:('a -> 'a -> int) -> 'a -> 'a t ->
|
||||||
[ `All_lower | `All_bigger | `Just_after of int | `Empty | `At of int ]
|
[ `All_lower | `All_bigger | `Just_after of int | `Empty | `At of int ]
|
||||||
(** [bsearch ?cmp key arr] finds the index of the object [key] in the array [arr],
|
(** [bsearch ?cmp x arr] finds the index of the object [x] in the array [arr],
|
||||||
provided [arr] is {b sorted} using [cmp]. If the array is not sorted,
|
provided [arr] is {b sorted} using [cmp]. If the array is not sorted,
|
||||||
the result is not specified (may raise Invalid_argument).
|
the result is not specified (may raise Invalid_argument).
|
||||||
|
|
||||||
|
|
@ -107,35 +107,35 @@ val bsearch : ?cmp:('a -> 'a -> int) -> key:'a -> 'a t ->
|
||||||
(dichotomic search).
|
(dichotomic search).
|
||||||
|
|
||||||
@return
|
@return
|
||||||
- [`At i] if [cmp arr.(i) key = 0] (for some i)
|
- [`At i] if [cmp arr.(i) x = 0] (for some i)
|
||||||
- [`All_lower] if all elements of [arr] are lower than [key]
|
- [`All_lower] if all elements of [arr] are lower than [x]
|
||||||
- [`All_bigger] if all elements of [arr] are bigger than [key]
|
- [`All_bigger] if all elements of [arr] are bigger than [x]
|
||||||
- [`Just_after i] if [arr.(i) < key < arr.(i+1)]
|
- [`Just_after i] if [arr.(i) < x < arr.(i+1)]
|
||||||
- [`Empty] if the array is empty
|
- [`Empty] if the array is empty
|
||||||
|
|
||||||
@raise Invalid_argument if the array is found to be unsorted w.r.t [cmp]
|
@raise Invalid_argument if the array is found to be unsorted w.r.t [cmp]
|
||||||
@since 0.13 *)
|
@since 0.13 *)
|
||||||
|
|
||||||
val for_all : f:('a -> bool) -> 'a t -> bool
|
val for_all : ('a -> bool) -> 'a t -> bool
|
||||||
|
|
||||||
val for_all2 : f:('a -> 'b -> bool) -> 'a t -> 'b t -> bool
|
val for_all2 : ('a -> 'b -> bool) -> 'a t -> 'b t -> bool
|
||||||
(** Forall on pairs of arrays.
|
(** Forall on pairs of arrays.
|
||||||
@raise Invalid_argument if they have distinct lengths
|
@raise Invalid_argument if they have distinct lengths
|
||||||
allow different types @since 0.20 *)
|
allow different types @since 0.20 *)
|
||||||
|
|
||||||
val exists : f:('a -> bool) -> 'a t -> bool
|
val exists : ('a -> bool) -> 'a t -> bool
|
||||||
|
|
||||||
val exists2 : f:('a -> 'b -> bool) -> 'a t -> 'b t -> bool
|
val exists2 : ('a -> 'b -> bool) -> 'a t -> 'b t -> bool
|
||||||
(** Exists on pairs of arrays.
|
(** Exists on pairs of arrays.
|
||||||
@raise Invalid_argument if they have distinct lengths
|
@raise Invalid_argument if they have distinct lengths
|
||||||
allow different types @since 0.20 *)
|
allow different types @since 0.20 *)
|
||||||
|
|
||||||
val fold2 : f:('acc -> 'a -> 'b -> 'acc) -> init:'acc -> 'a t -> 'b t -> 'acc
|
val fold2 : ('acc -> 'a -> 'b -> 'acc) -> 'acc -> 'a t -> 'b t -> 'acc
|
||||||
(** Fold on two arrays stepwise.
|
(** Fold on two arrays stepwise.
|
||||||
@raise Invalid_argument if they have distinct lengths
|
@raise Invalid_argument if they have distinct lengths
|
||||||
@since 0.20 *)
|
@since 0.20 *)
|
||||||
|
|
||||||
val iter2 : f:('a -> 'b -> unit) -> 'a t -> 'b t -> unit
|
val iter2 : ('a -> 'b -> unit) -> 'a t -> 'b t -> unit
|
||||||
(** Iterate on two arrays stepwise.
|
(** Iterate on two arrays stepwise.
|
||||||
@raise Invalid_argument if they have distinct lengths
|
@raise Invalid_argument if they have distinct lengths
|
||||||
@since 0.20 *)
|
@since 0.20 *)
|
||||||
|
|
@ -162,9 +162,9 @@ val pp: ?sep:string -> 'a printer -> 'a t printer
|
||||||
val pp_i: ?sep:string -> (int -> 'a printer) -> 'a t printer
|
val pp_i: ?sep:string -> (int -> 'a printer) -> 'a t printer
|
||||||
(** Print an array, giving the printing function both index and item *)
|
(** Print an array, giving the printing function both index and item *)
|
||||||
|
|
||||||
val map : f:('a -> 'b) -> 'a t -> 'b t
|
val map : ('a -> 'b) -> 'a t -> 'b t
|
||||||
|
|
||||||
val map2 : f:('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t
|
val map2 : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t
|
||||||
(** Map on two arrays stepwise.
|
(** Map on two arrays stepwise.
|
||||||
@raise Invalid_argument if they have distinct lengths
|
@raise Invalid_argument if they have distinct lengths
|
||||||
@since 0.20 *)
|
@since 0.20 *)
|
||||||
|
|
@ -173,14 +173,14 @@ val rev : 'a t -> 'a t
|
||||||
(** Copy + reverse in place
|
(** Copy + reverse in place
|
||||||
@since 0.20 *)
|
@since 0.20 *)
|
||||||
|
|
||||||
val filter : f:('a -> bool) -> 'a t -> 'a t
|
val filter : ('a -> bool) -> 'a t -> 'a t
|
||||||
(** Filter elements out of the array. Only the elements satisfying
|
(** Filter elements out of the array. Only the elements satisfying
|
||||||
the given predicate will be kept. *)
|
the given predicate will be kept. *)
|
||||||
|
|
||||||
val filter_map : f:('a -> 'b option) -> 'a t -> 'b t
|
val filter_map : ('a -> 'b option) -> 'a t -> 'b t
|
||||||
(** Map each element into another value, or discard it *)
|
(** Map each element into another value, or discard it *)
|
||||||
|
|
||||||
val flat_map : f:('a -> 'b t) -> 'a t -> 'b array
|
val flat_map : ('a -> 'b t) -> 'a t -> 'b array
|
||||||
(** Transform each element into an array, then flatten *)
|
(** Transform each element into an array, then flatten *)
|
||||||
|
|
||||||
val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
|
val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
|
||||||
|
|
|
||||||
1
src/core/CCArrayLabels.ml
Symbolic link
1
src/core/CCArrayLabels.ml
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
CCArray.ml
|
||||||
229
src/core/CCArrayLabels.mli
Normal file
229
src/core/CCArrayLabels.mli
Normal file
|
|
@ -0,0 +1,229 @@
|
||||||
|
|
||||||
|
(* This file is free software, part of containers. See file "license" for more details. *)
|
||||||
|
|
||||||
|
(** {1 Array utils} *)
|
||||||
|
|
||||||
|
type 'a sequence = ('a -> unit) -> unit
|
||||||
|
type 'a klist = unit -> [`Nil | `Cons of 'a * 'a klist]
|
||||||
|
type 'a gen = unit -> 'a option
|
||||||
|
type 'a equal = 'a -> 'a -> bool
|
||||||
|
type 'a ord = 'a -> 'a -> int
|
||||||
|
type 'a random_gen = Random.State.t -> 'a
|
||||||
|
type 'a printer = Format.formatter -> 'a -> unit
|
||||||
|
|
||||||
|
(** {2 Arrays} *)
|
||||||
|
|
||||||
|
type 'a t = 'a array
|
||||||
|
|
||||||
|
val empty : 'a t
|
||||||
|
|
||||||
|
val equal : 'a equal -> 'a t equal
|
||||||
|
|
||||||
|
val compare : 'a ord -> 'a t ord
|
||||||
|
|
||||||
|
val get : 'a t -> int -> 'a
|
||||||
|
|
||||||
|
val get_safe : 'a t -> int -> 'a option
|
||||||
|
(** [get_safe a i] returns [Some a.(i)] if [i] is a valid index
|
||||||
|
@since 0.18 *)
|
||||||
|
|
||||||
|
val set : 'a t -> int -> 'a -> unit
|
||||||
|
|
||||||
|
val length : _ t -> int
|
||||||
|
|
||||||
|
val fold : f:('a -> 'b -> 'a) -> init:'a -> 'b t -> 'a
|
||||||
|
|
||||||
|
val foldi : f:('a -> int -> 'b -> 'a) -> init:'a -> 'b t -> 'a
|
||||||
|
(** Fold left on array, with index *)
|
||||||
|
|
||||||
|
val fold_while : f:('a -> 'b -> 'a * [`Stop | `Continue]) -> init:'a -> 'b t -> 'a
|
||||||
|
(** Fold left on array until a stop condition via [('a, `Stop)] is
|
||||||
|
indicated by the accumulator
|
||||||
|
@since 0.8 *)
|
||||||
|
|
||||||
|
val iter : f:('a -> unit) -> 'a t -> unit
|
||||||
|
|
||||||
|
val iteri : f:(int -> 'a -> unit) -> 'a t -> unit
|
||||||
|
|
||||||
|
val blit : 'a t -> int -> 'a t -> int -> int -> unit
|
||||||
|
(** [blit from i into j len] copies [len] elements from the first array
|
||||||
|
to the second. See {!Array.blit}. *)
|
||||||
|
|
||||||
|
val reverse_in_place : 'a t -> unit
|
||||||
|
(** Reverse the array in place *)
|
||||||
|
|
||||||
|
val sorted : f:('a -> 'a -> int) -> 'a t -> 'a array
|
||||||
|
(** [sorted cmp a] makes a copy of [a] and sorts it with [cmp].
|
||||||
|
@since NEXT_RELEASE *)
|
||||||
|
|
||||||
|
val sort_indices : f:('a -> 'a -> int) -> 'a t -> int array
|
||||||
|
(** [sort_indices cmp a] returns a new array [b], with the same length as [a],
|
||||||
|
such that [b.(i)] is the index of the [i]-th element of [a] in [sort cmp a].
|
||||||
|
In other words, [map (fun i -> a.(i)) (sort_indices a) = sorted cmp a].
|
||||||
|
[a] is not modified.
|
||||||
|
@since NEXT_RELEASE *)
|
||||||
|
|
||||||
|
val sort_ranking : f:('a -> 'a -> int) -> 'a t -> int array
|
||||||
|
(** [sort_ranking cmp a] returns a new array [b], with the same length as [a],
|
||||||
|
such that [b.(i)] is the position in [sorted cmp a] of the [i]-th
|
||||||
|
element of [a].
|
||||||
|
[a] is not modified.
|
||||||
|
|
||||||
|
In other words, [map (fun i -> (sorted cmp a).(i)) (sort_ranking cmp a) = a].
|
||||||
|
|
||||||
|
Without duplicates, we also have
|
||||||
|
[lookup_exn a.(i) (sorted a) = (sorted_ranking a).(i)]
|
||||||
|
@since NEXT_RELEASE *)
|
||||||
|
|
||||||
|
val find : f:('a -> 'b option) -> 'a t -> 'b option
|
||||||
|
(** [find f a] returns [Some y] if there is an element [x] such
|
||||||
|
that [f x = Some y], else it returns [None] *)
|
||||||
|
|
||||||
|
val findi : f:(int -> 'a -> 'b option) -> 'a t -> 'b option
|
||||||
|
(** Like {!find}, but also pass the index to the predicate function.
|
||||||
|
@since 0.3.4 *)
|
||||||
|
|
||||||
|
val find_idx : f:('a -> bool) -> 'a t -> (int * 'a) option
|
||||||
|
(** [find_idx p x] returns [Some (i,x)] where [x] is the [i]-th element of [l],
|
||||||
|
and [p x] holds. Otherwise returns [None]
|
||||||
|
@since 0.3.4 *)
|
||||||
|
|
||||||
|
val lookup : ?cmp:'a ord -> key:'a -> 'a t -> int option
|
||||||
|
(** Lookup the index of some value in a sorted array.
|
||||||
|
@return [None] if the key is not present, or
|
||||||
|
[Some i] ([i] the index of the key) otherwise *)
|
||||||
|
|
||||||
|
val lookup_exn : ?cmp:'a ord -> key:'a -> 'a t -> int
|
||||||
|
(** Same as {!lookup_exn}, but
|
||||||
|
@raise Not_found if the key is not present *)
|
||||||
|
|
||||||
|
val bsearch : ?cmp:('a -> 'a -> int) -> key:'a -> 'a t ->
|
||||||
|
[ `All_lower | `All_bigger | `Just_after of int | `Empty | `At of int ]
|
||||||
|
(** [bsearch ?cmp key arr] finds the index of the object [key] in the array [arr],
|
||||||
|
provided [arr] is {b sorted} using [cmp]. If the array is not sorted,
|
||||||
|
the result is not specified (may raise Invalid_argument).
|
||||||
|
|
||||||
|
Complexity: O(log n) where n is the length of the array
|
||||||
|
(dichotomic search).
|
||||||
|
|
||||||
|
@return
|
||||||
|
- [`At i] if [cmp arr.(i) key = 0] (for some i)
|
||||||
|
- [`All_lower] if all elements of [arr] are lower than [key]
|
||||||
|
- [`All_bigger] if all elements of [arr] are bigger than [key]
|
||||||
|
- [`Just_after i] if [arr.(i) < key < arr.(i+1)]
|
||||||
|
- [`Empty] if the array is empty
|
||||||
|
|
||||||
|
@raise Invalid_argument if the array is found to be unsorted w.r.t [cmp]
|
||||||
|
@since 0.13 *)
|
||||||
|
|
||||||
|
val for_all : f:('a -> bool) -> 'a t -> bool
|
||||||
|
|
||||||
|
val for_all2 : f:('a -> 'b -> bool) -> 'a t -> 'b t -> bool
|
||||||
|
(** Forall on pairs of arrays.
|
||||||
|
@raise Invalid_argument if they have distinct lengths
|
||||||
|
allow different types @since 0.20 *)
|
||||||
|
|
||||||
|
val exists : f:('a -> bool) -> 'a t -> bool
|
||||||
|
|
||||||
|
val exists2 : f:('a -> 'b -> bool) -> 'a t -> 'b t -> bool
|
||||||
|
(** Exists on pairs of arrays.
|
||||||
|
@raise Invalid_argument if they have distinct lengths
|
||||||
|
allow different types @since 0.20 *)
|
||||||
|
|
||||||
|
val fold2 : f:('acc -> 'a -> 'b -> 'acc) -> init:'acc -> 'a t -> 'b t -> 'acc
|
||||||
|
(** Fold on two arrays stepwise.
|
||||||
|
@raise Invalid_argument if they have distinct lengths
|
||||||
|
@since 0.20 *)
|
||||||
|
|
||||||
|
val iter2 : f:('a -> 'b -> unit) -> 'a t -> 'b t -> unit
|
||||||
|
(** Iterate on two arrays stepwise.
|
||||||
|
@raise Invalid_argument if they have distinct lengths
|
||||||
|
@since 0.20 *)
|
||||||
|
|
||||||
|
val shuffle : 'a t -> unit
|
||||||
|
(** Shuffle randomly the array, in place *)
|
||||||
|
|
||||||
|
val shuffle_with : Random.State.t -> 'a t -> unit
|
||||||
|
(** Like shuffle but using a specialized random state *)
|
||||||
|
|
||||||
|
val random_choose : 'a t -> 'a random_gen
|
||||||
|
(** Choose an element randomly.
|
||||||
|
@raise Not_found if the array/slice is empty *)
|
||||||
|
|
||||||
|
val to_seq : 'a t -> 'a sequence
|
||||||
|
val to_gen : 'a t -> 'a gen
|
||||||
|
val to_klist : 'a t -> 'a klist
|
||||||
|
|
||||||
|
(** {2 IO} *)
|
||||||
|
|
||||||
|
val pp: ?sep:string -> 'a printer -> 'a t printer
|
||||||
|
(** Print an array of items with printing function *)
|
||||||
|
|
||||||
|
val pp_i: ?sep:string -> (int -> 'a printer) -> 'a t printer
|
||||||
|
(** Print an array, giving the printing function both index and item *)
|
||||||
|
|
||||||
|
val map : f:('a -> 'b) -> 'a t -> 'b t
|
||||||
|
|
||||||
|
val map2 : f:('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t
|
||||||
|
(** Map on two arrays stepwise.
|
||||||
|
@raise Invalid_argument if they have distinct lengths
|
||||||
|
@since 0.20 *)
|
||||||
|
|
||||||
|
val rev : 'a t -> 'a t
|
||||||
|
(** Copy + reverse in place
|
||||||
|
@since 0.20 *)
|
||||||
|
|
||||||
|
val filter : f:('a -> bool) -> 'a t -> 'a t
|
||||||
|
(** Filter elements out of the array. Only the elements satisfying
|
||||||
|
the given predicate will be kept. *)
|
||||||
|
|
||||||
|
val filter_map : f:('a -> 'b option) -> 'a t -> 'b t
|
||||||
|
(** Map each element into another value, or discard it *)
|
||||||
|
|
||||||
|
val flat_map : f:('a -> 'b t) -> 'a t -> 'b array
|
||||||
|
(** Transform each element into an array, then flatten *)
|
||||||
|
|
||||||
|
val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
|
||||||
|
(** Infix version of {!flat_map} *)
|
||||||
|
|
||||||
|
val (>>|) : 'a t -> ('a -> 'b) -> 'b t
|
||||||
|
(** Infix version of {!map}
|
||||||
|
@since 0.8 *)
|
||||||
|
|
||||||
|
val (>|=) : 'a t -> ('a -> 'b) -> 'b t
|
||||||
|
(** Infix version of {!map}
|
||||||
|
@since 0.8 *)
|
||||||
|
|
||||||
|
val except_idx : 'a t -> int -> 'a list
|
||||||
|
(** Remove given index, obtaining the list of the other elements *)
|
||||||
|
|
||||||
|
val (--) : int -> int -> int t
|
||||||
|
(** Range array *)
|
||||||
|
|
||||||
|
val (--^) : int -> int -> int t
|
||||||
|
(** Range array, excluding right bound
|
||||||
|
@since 0.17 *)
|
||||||
|
|
||||||
|
val random : 'a random_gen -> 'a t random_gen
|
||||||
|
val random_non_empty : 'a random_gen -> 'a t random_gen
|
||||||
|
val random_len : int -> 'a random_gen -> 'a t random_gen
|
||||||
|
|
||||||
|
(** {2 Generic Functions} *)
|
||||||
|
|
||||||
|
module type MONO_ARRAY = sig
|
||||||
|
type elt
|
||||||
|
type t
|
||||||
|
|
||||||
|
val length : t -> int
|
||||||
|
|
||||||
|
val get : t -> int -> elt
|
||||||
|
|
||||||
|
val set : t -> int -> elt -> unit
|
||||||
|
end
|
||||||
|
|
||||||
|
val sort_generic :
|
||||||
|
(module MONO_ARRAY with type t = 'arr and type elt = 'elt) ->
|
||||||
|
?cmp:('elt -> 'elt -> int) -> 'arr -> unit
|
||||||
|
(** Sort the array, without allocating (eats stack space though). Performance
|
||||||
|
might be lower than {!Array.sort}.
|
||||||
|
@since 0.14 *)
|
||||||
|
|
@ -18,7 +18,7 @@ let is_empty = function
|
||||||
(* max depth for direct recursion *)
|
(* max depth for direct recursion *)
|
||||||
let direct_depth_default_ = 1000
|
let direct_depth_default_ = 1000
|
||||||
|
|
||||||
let map ~f l =
|
let map f l =
|
||||||
let rec direct f i l = match l with
|
let rec direct f i l = match l with
|
||||||
| [] -> []
|
| [] -> []
|
||||||
| [x] -> [f x]
|
| [x] -> [f x]
|
||||||
|
|
@ -40,7 +40,7 @@ let map ~f l =
|
||||||
List.rev (List.rev_map f l) = map f l)
|
List.rev (List.rev_map f l) = map f l)
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let (>|=) l f = map ~f:f l
|
let (>|=) l f = map f l
|
||||||
|
|
||||||
let direct_depth_append_ = 10_000
|
let direct_depth_append_ = 10_000
|
||||||
|
|
||||||
|
|
@ -78,7 +78,7 @@ let cons_maybe o l = match o with
|
||||||
|
|
||||||
let direct_depth_filter_ = 10_000
|
let direct_depth_filter_ = 10_000
|
||||||
|
|
||||||
let filter ~f l =
|
let filter p l =
|
||||||
let rec direct i p l = match l with
|
let rec direct i p l = match l with
|
||||||
| [] -> []
|
| [] -> []
|
||||||
| _ when i=0 -> safe p l []
|
| _ when i=0 -> safe p l []
|
||||||
|
|
@ -89,7 +89,7 @@ let filter ~f l =
|
||||||
| x::l' when not (p x) -> safe p l' acc
|
| x::l' when not (p x) -> safe p l' acc
|
||||||
| x::l' -> safe p l' (x::acc)
|
| x::l' -> safe p l' (x::acc)
|
||||||
in
|
in
|
||||||
direct direct_depth_filter_ f l
|
direct direct_depth_filter_ p l
|
||||||
|
|
||||||
(*$= & ~printer:CCInt.to_string
|
(*$= & ~printer:CCInt.to_string
|
||||||
500 (filter (fun x->x mod 2 = 0) (1 -- 1000) |> List.length)
|
500 (filter (fun x->x mod 2 = 0) (1 -- 1000) |> List.length)
|
||||||
|
|
@ -122,38 +122,37 @@ let fold_right f l acc =
|
||||||
l = fold_right (fun x y->x::y) l [])
|
l = fold_right (fun x y->x::y) l [])
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let rec fold_while ~f ~init:acc = function
|
let rec fold_while f acc = function
|
||||||
| [] -> acc
|
| [] -> acc
|
||||||
| e::l -> let acc, cont = f acc e in
|
| e::l -> let acc, cont = f acc e in
|
||||||
match cont with
|
match cont with
|
||||||
| `Stop -> acc
|
| `Stop -> acc
|
||||||
| `Continue -> fold_while ~f ~init:acc l
|
| `Continue -> fold_while f acc l
|
||||||
|
|
||||||
(*$T
|
(*$T
|
||||||
fold_while ~f:(fun acc b -> if b then acc+1, `Continue else acc, `Stop) \
|
fold_while (fun acc b -> if b then acc+1, `Continue else acc, `Stop) 0 [true;true;false;true] = 2
|
||||||
~init:0 [true;true;false;true] = 2
|
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let fold_map ~f ~init l =
|
let fold_map f acc l =
|
||||||
let rec aux f acc map_acc l = match l with
|
let rec aux f acc map_acc l = match l with
|
||||||
| [] -> acc, List.rev map_acc
|
| [] -> acc, List.rev map_acc
|
||||||
| x :: l' ->
|
| x :: l' ->
|
||||||
let acc, y = f acc x in
|
let acc, y = f acc x in
|
||||||
aux f acc (y :: map_acc) l'
|
aux f acc (y :: map_acc) l'
|
||||||
in
|
in
|
||||||
aux f init [] l
|
aux f acc [] l
|
||||||
|
|
||||||
(*$=
|
(*$=
|
||||||
(6, ["1"; "2"; "3"]) \
|
(6, ["1"; "2"; "3"]) \
|
||||||
(fold_map ~f:(fun acc x->acc+x, string_of_int x) ~init:0 [1;2;3])
|
(fold_map (fun acc x->acc+x, string_of_int x) 0 [1;2;3])
|
||||||
*)
|
*)
|
||||||
|
|
||||||
(*$Q
|
(*$Q
|
||||||
Q.(list int) (fun l -> \
|
Q.(list int) (fun l -> \
|
||||||
fold_map ~f:(fun acc x -> x::acc, x) ~init:[] l = (List.rev l, l))
|
fold_map (fun acc x -> x::acc, x) [] l = (List.rev l, l))
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let fold_map2 ~f ~init l1 l2 =
|
let fold_map2 f acc l1 l2 =
|
||||||
let rec aux f acc map_acc l1 l2 = match l1, l2 with
|
let rec aux f acc map_acc l1 l2 = match l1, l2 with
|
||||||
| [], [] -> acc, List.rev map_acc
|
| [], [] -> acc, List.rev map_acc
|
||||||
| [], _
|
| [], _
|
||||||
|
|
@ -162,56 +161,56 @@ let fold_map2 ~f ~init l1 l2 =
|
||||||
let acc, y = f acc x1 x2 in
|
let acc, y = f acc x1 x2 in
|
||||||
aux f acc (y :: map_acc) l1' l2'
|
aux f acc (y :: map_acc) l1' l2'
|
||||||
in
|
in
|
||||||
aux f init [] l1 l2
|
aux f acc [] l1 l2
|
||||||
|
|
||||||
(*$=
|
(*$=
|
||||||
(310, ["1 10"; "2 0"; "3 100"]) \
|
(310, ["1 10"; "2 0"; "3 100"]) \
|
||||||
(fold_map2 ~f:(fun acc x y->acc+x*y, string_of_int x ^ " " ^ string_of_int y) \
|
(fold_map2 (fun acc x y->acc+x*y, string_of_int x ^ " " ^ string_of_int y) \
|
||||||
~init:0 [1;2;3] [10;0;100])
|
0 [1;2;3] [10;0;100])
|
||||||
*)
|
*)
|
||||||
|
|
||||||
(*$T
|
(*$T
|
||||||
(try ignore (fold_map2 ~f:(fun _ _ _ -> assert false) ~init:42 [] [1]); false \
|
(try ignore (fold_map2 (fun _ _ _ -> assert false) 42 [] [1]); false \
|
||||||
with Invalid_argument _ -> true)
|
with Invalid_argument _ -> true)
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let fold_filter_map ~f ~init l =
|
let fold_filter_map f acc l =
|
||||||
let rec aux f acc map_acc l = match l with
|
let rec aux f acc map_acc l = match l with
|
||||||
| [] -> acc, List.rev map_acc
|
| [] -> acc, List.rev map_acc
|
||||||
| x :: l' ->
|
| x :: l' ->
|
||||||
let acc, y = f acc x in
|
let acc, y = f acc x in
|
||||||
aux f acc (cons_maybe y map_acc) l'
|
aux f acc (cons_maybe y map_acc) l'
|
||||||
in
|
in
|
||||||
aux f init [] l
|
aux f acc [] l
|
||||||
|
|
||||||
(*$= & ~printer:Q.Print.(pair int (list int))
|
(*$= & ~printer:Q.Print.(pair int (list int))
|
||||||
(List.fold_left (+) 0 (1--10), [2;4;6;8;10]) \
|
(List.fold_left (+) 0 (1--10), [2;4;6;8;10]) \
|
||||||
(fold_filter_map ~f:(fun acc x -> acc+x, if x mod 2 = 0 then Some x else None) \
|
(fold_filter_map (fun acc x -> acc+x, if x mod 2 = 0 then Some x else None) \
|
||||||
~init:0 (1--10))
|
0 (1--10))
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let fold_flat_map ~f ~init l =
|
let fold_flat_map f acc l =
|
||||||
let rec aux f acc map_acc l = match l with
|
let rec aux f acc map_acc l = match l with
|
||||||
| [] -> acc, List.rev map_acc
|
| [] -> acc, List.rev map_acc
|
||||||
| x :: l' ->
|
| x :: l' ->
|
||||||
let acc, y = f acc x in
|
let acc, y = f acc x in
|
||||||
aux f acc (List.rev_append y map_acc) l'
|
aux f acc (List.rev_append y map_acc) l'
|
||||||
in
|
in
|
||||||
aux f init [] l
|
aux f acc [] l
|
||||||
|
|
||||||
(*$=
|
(*$=
|
||||||
(6, ["1"; "a1"; "2"; "a2"; "3"; "a3"]) \
|
(6, ["1"; "a1"; "2"; "a2"; "3"; "a3"]) \
|
||||||
(let pf = Printf.sprintf in \
|
(let pf = Printf.sprintf in \
|
||||||
fold_flat_map ~f:(fun acc x->acc+x, [pf "%d" x; pf "a%d" x]) ~init:0 [1;2;3])
|
fold_flat_map (fun acc x->acc+x, [pf "%d" x; pf "a%d" x]) 0 [1;2;3])
|
||||||
*)
|
*)
|
||||||
|
|
||||||
(*$Q
|
(*$Q
|
||||||
Q.(list int) (fun l -> \
|
Q.(list int) (fun l -> \
|
||||||
fold_flat_map ~f:(fun acc x -> x::acc, [x;x+10]) ~init:[] l = \
|
fold_flat_map (fun acc x -> x::acc, [x;x+10]) [] l = \
|
||||||
(List.rev l, flat_map ~f:(fun x->[x;x+10]) l) )
|
(List.rev l, flat_map (fun x->[x;x+10]) l) )
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let init len ~f =
|
let init len f =
|
||||||
let rec init_rec acc i f =
|
let rec init_rec acc i f =
|
||||||
if i=0 then f i :: acc
|
if i=0 then f i :: acc
|
||||||
else init_rec (f i :: acc) (i-1) f
|
else init_rec (f i :: acc) (i-1) f
|
||||||
|
|
@ -221,9 +220,9 @@ let init len ~f =
|
||||||
else init_rec [] (len-1) f
|
else init_rec [] (len-1) f
|
||||||
|
|
||||||
(*$T
|
(*$T
|
||||||
init 0 ~f:(fun _ -> 0) = []
|
init 0 (fun _ -> 0) = []
|
||||||
init 1 ~f:(fun x->x) = [0]
|
init 1 (fun x->x) = [0]
|
||||||
init 1000 ~f:(fun x->x) = 0--999
|
init 1000 (fun x->x) = 0--999
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let rec compare f l1 l2 = match l1, l2 with
|
let rec compare f l1 l2 = match l1, l2 with
|
||||||
|
|
@ -243,7 +242,7 @@ let rec equal f l1 l2 = match l1, l2 with
|
||||||
equal CCInt.equal (1--1_000_000) (1--1_000_000)
|
equal CCInt.equal (1--1_000_000) (1--1_000_000)
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let flat_map ~f l =
|
let flat_map f l =
|
||||||
let rec aux f l kont = match l with
|
let rec aux f l kont = match l with
|
||||||
| [] -> kont []
|
| [] -> kont []
|
||||||
| x::l' ->
|
| x::l' ->
|
||||||
|
|
@ -267,19 +266,19 @@ let flatten l = fold_right append l []
|
||||||
|
|
||||||
(*$T
|
(*$T
|
||||||
flatten [[1]; [2;3;4]; []; []; [5;6]] = 1--6
|
flatten [[1]; [2;3;4]; []; []; [5;6]] = 1--6
|
||||||
flatten (init 300_001 ~f:(fun x->[x])) = 0--300_000
|
flatten (init 300_001 (fun x->[x])) = 0--300_000
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let product ~f l1 l2 =
|
let product f l1 l2 =
|
||||||
flat_map ~f:(fun x -> map ~f:(fun y -> f x y) l2) l1
|
flat_map (fun x -> map (fun y -> f x y) l2) l1
|
||||||
|
|
||||||
let fold_product ~f ~init l1 l2 =
|
let fold_product f acc l1 l2 =
|
||||||
List.fold_left
|
List.fold_left
|
||||||
(fun acc x1 ->
|
(fun acc x1 ->
|
||||||
List.fold_left
|
List.fold_left
|
||||||
(fun acc x2 -> f acc x1 x2)
|
(fun acc x2 -> f acc x1 x2)
|
||||||
acc l2)
|
acc l2
|
||||||
init l1
|
) acc l1
|
||||||
|
|
||||||
let diagonal l =
|
let diagonal l =
|
||||||
let rec gen acc l = match l with
|
let rec gen acc l = match l with
|
||||||
|
|
@ -297,7 +296,7 @@ let diagonal l =
|
||||||
diagonal [1;2;3] |> List.sort Pervasives.compare = [1, 2; 1, 3; 2, 3]
|
diagonal [1;2;3] |> List.sort Pervasives.compare = [1, 2; 1, 3; 2, 3]
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let partition_map ~f l =
|
let partition_map f l =
|
||||||
let rec iter f l1 l2 l = match l with
|
let rec iter f l1 l2 l = match l with
|
||||||
| [] -> List.rev l1, List.rev l2
|
| [] -> List.rev l1, List.rev l2
|
||||||
| x :: tl ->
|
| x :: tl ->
|
||||||
|
|
@ -310,11 +309,11 @@ let partition_map ~f l =
|
||||||
|
|
||||||
(*$R
|
(*$R
|
||||||
let l1, l2 =
|
let l1, l2 =
|
||||||
partition_map ~f:(function
|
partition_map (function
|
||||||
| n when n = 0 -> `Drop
|
| n when n = 0 -> `Drop
|
||||||
| n when n mod 2 = 0 -> `Left n
|
| n when n mod 2 = 0 -> `Left n
|
||||||
| n -> `Right n)
|
| n -> `Right n
|
||||||
[0;1;2;3;4]
|
) [0;1;2;3;4]
|
||||||
in
|
in
|
||||||
assert_equal [2;4] l1;
|
assert_equal [2;4] l1;
|
||||||
assert_equal [1;3] l2
|
assert_equal [1;3] l2
|
||||||
|
|
@ -322,13 +321,13 @@ let partition_map ~f l =
|
||||||
|
|
||||||
let return x = [x]
|
let return x = [x]
|
||||||
|
|
||||||
let (>>=) l f = flat_map ~f l
|
let (>>=) l f = flat_map f l
|
||||||
|
|
||||||
let (<$>) f x = map ~f x
|
let (<$>) = map
|
||||||
|
|
||||||
let pure = return
|
let pure = return
|
||||||
|
|
||||||
let (<*>) funs l = product ~f:(fun f x -> f x) funs l
|
let (<*>) funs l = product (fun f x -> f x) funs l
|
||||||
|
|
||||||
let sorted_merge ?(cmp=Pervasives.compare) l1 l2 =
|
let sorted_merge ?(cmp=Pervasives.compare) l1 l2 =
|
||||||
let rec recurse cmp acc l1 l2 = match l1,l2 with
|
let rec recurse cmp acc l1 l2 = match l1,l2 with
|
||||||
|
|
@ -531,7 +530,7 @@ let split = take_drop
|
||||||
l1 @ l2 = l )
|
l1 @ l2 = l )
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let take_while ~f l =
|
let take_while p l =
|
||||||
let rec direct i p l = match l with
|
let rec direct i p l = match l with
|
||||||
| [] -> []
|
| [] -> []
|
||||||
| _ when i=0 -> safe p [] l
|
| _ when i=0 -> safe p [] l
|
||||||
|
|
@ -542,13 +541,13 @@ let take_while ~f l =
|
||||||
| x :: l' ->
|
| x :: l' ->
|
||||||
if p x then safe p (x::acc) l' else List.rev acc
|
if p x then safe p (x::acc) l' else List.rev acc
|
||||||
in
|
in
|
||||||
direct direct_depth_default_ f l
|
direct direct_depth_default_ p l
|
||||||
|
|
||||||
(*$T
|
(*$T
|
||||||
take_while ~f:(fun x->x<10) (1 -- 20) = (1--9)
|
take_while (fun x->x<10) (1 -- 20) = (1--9)
|
||||||
take_while ~f:(fun x->x <> 0) [0;1;2;3] = []
|
take_while (fun x->x <> 0) [0;1;2;3] = []
|
||||||
take_while ~f:(fun _ -> true) [] = []
|
take_while (fun _ -> true) [] = []
|
||||||
take_while ~f:(fun _ -> true) (1--10) = (1--10)
|
take_while (fun _ -> true) (1--10) = (1--10)
|
||||||
*)
|
*)
|
||||||
|
|
||||||
(*$Q
|
(*$Q
|
||||||
|
|
@ -557,9 +556,9 @@ let take_while ~f l =
|
||||||
List.for_all f l1)
|
List.for_all f l1)
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let rec drop_while ~f l = match l with
|
let rec drop_while p l = match l with
|
||||||
| [] -> []
|
| [] -> []
|
||||||
| x :: l' -> if f x then drop_while ~f l' else l
|
| x :: l' -> if p x then drop_while p l' else l
|
||||||
|
|
||||||
(*$Q
|
(*$Q
|
||||||
Q.(pair (fun1 small_int bool) (list small_int)) (fun (f,l) -> \
|
Q.(pair (fun1 small_int bool) (list small_int)) (fun (f,l) -> \
|
||||||
|
|
@ -588,23 +587,23 @@ let rec last_opt = function
|
||||||
None (last_opt [])
|
None (last_opt [])
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let rec find_pred ~f l = match l with
|
let rec find_pred p l = match l with
|
||||||
| [] -> None
|
| [] -> None
|
||||||
| x :: _ when f x -> Some x
|
| x :: _ when p x -> Some x
|
||||||
| _ :: tl -> find_pred ~f tl
|
| _ :: tl -> find_pred p tl
|
||||||
|
|
||||||
let find_pred_exn ~f l = match find_pred ~f l with
|
let find_pred_exn p l = match find_pred p l with
|
||||||
| None -> raise Not_found
|
| None -> raise Not_found
|
||||||
| Some x -> x
|
| Some x -> x
|
||||||
|
|
||||||
(*$T
|
(*$T
|
||||||
find_pred ~f:((=) 4) [1;2;5;4;3;0] = Some 4
|
find_pred ((=) 4) [1;2;5;4;3;0] = Some 4
|
||||||
find_pred ~f:(fun _ -> true) [] = None
|
find_pred (fun _ -> true) [] = None
|
||||||
find_pred ~f:(fun _ -> false) (1 -- 10) = None
|
find_pred (fun _ -> false) (1 -- 10) = None
|
||||||
find_pred ~f:(fun x -> x < 10) (1 -- 9) = Some 1
|
find_pred (fun x -> x < 10) (1 -- 9) = Some 1
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let find_mapi ~f l =
|
let find_mapi f l =
|
||||||
let rec aux f i = function
|
let rec aux f i = function
|
||||||
| [] -> None
|
| [] -> None
|
||||||
| x::l' ->
|
| x::l' ->
|
||||||
|
|
@ -613,32 +612,32 @@ let find_mapi ~f l =
|
||||||
| None -> aux f (i+1) l'
|
| None -> aux f (i+1) l'
|
||||||
in aux f 0 l
|
in aux f 0 l
|
||||||
|
|
||||||
let find_map ~f l = find_mapi ~f:(fun _ -> f) l
|
let find_map f l = find_mapi (fun _ -> f) l
|
||||||
|
|
||||||
let find = find_map
|
let find = find_map
|
||||||
let findi = find_mapi
|
let findi = find_mapi
|
||||||
|
|
||||||
let find_idx ~f l = find_mapi ~f:(fun i x -> if f x then Some (i, x) else None) l
|
let find_idx p l = find_mapi (fun i x -> if p x then Some (i, x) else None) l
|
||||||
|
|
||||||
(*$T
|
(*$T
|
||||||
find (fun x -> if x=3 then Some "a" else None) [1;2;3;4] = Some "a"
|
find (fun x -> if x=3 then Some "a" else None) [1;2;3;4] = Some "a"
|
||||||
find (fun x -> if x=3 then Some "a" else None) [1;2;4;5] = None
|
find (fun x -> if x=3 then Some "a" else None) [1;2;4;5] = None
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let remove ?(eq=(=)) ~key l =
|
let remove ?(eq=(=)) ~x l =
|
||||||
let rec remove' eq x acc l = match l with
|
let rec remove' eq x acc l = match l with
|
||||||
| [] -> List.rev acc
|
| [] -> List.rev acc
|
||||||
| y :: tail when eq x y -> remove' eq x acc tail
|
| y :: tail when eq x y -> remove' eq x acc tail
|
||||||
| y :: tail -> remove' eq x (y::acc) tail
|
| y :: tail -> remove' eq x (y::acc) tail
|
||||||
in
|
in
|
||||||
remove' eq key [] l
|
remove' eq x [] l
|
||||||
|
|
||||||
(*$T
|
(*$T
|
||||||
remove ~key:1 [2;1;3;3;2;1] = [2;3;3;2]
|
remove ~x:1 [2;1;3;3;2;1] = [2;3;3;2]
|
||||||
remove ~key:10 [1;2;3] = [1;2;3]
|
remove ~x:10 [1;2;3] = [1;2;3]
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let filter_map ~f l =
|
let filter_map f l =
|
||||||
let rec recurse acc l = match l with
|
let rec recurse acc l = match l with
|
||||||
| [] -> List.rev acc
|
| [] -> List.rev acc
|
||||||
| x::l' ->
|
| x::l' ->
|
||||||
|
|
@ -719,32 +718,32 @@ let inter ?(eq=(=)) l1 l2 =
|
||||||
inter [1;2;4] [2;3;4;5] = [2;4]
|
inter [1;2;4] [2;3;4;5] = [2;4]
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let mapi ~f l =
|
let mapi f l =
|
||||||
let r = ref 0 in
|
let r = ref 0 in
|
||||||
map l
|
map
|
||||||
~f:(fun x ->
|
(fun x ->
|
||||||
let y = f !r x in
|
let y = f !r x in
|
||||||
incr r;
|
incr r; y
|
||||||
y)
|
) l
|
||||||
|
|
||||||
(*$T
|
(*$T
|
||||||
mapi ~f:(fun i x -> i*x) [10;10;10] = [0;10;20]
|
mapi (fun i x -> i*x) [10;10;10] = [0;10;20]
|
||||||
*)
|
*)
|
||||||
|
|
||||||
let iteri ~f l =
|
let iteri f l =
|
||||||
let rec aux f i l = match l with
|
let rec aux f i l = match l with
|
||||||
| [] -> ()
|
| [] -> ()
|
||||||
| x::l' -> f i x; aux f (i+1) l'
|
| x::l' -> f i x; aux f (i+1) l'
|
||||||
in aux f 0 l
|
in aux f 0 l
|
||||||
|
|
||||||
let foldi ~f ~init l =
|
let foldi f acc l =
|
||||||
let rec foldi f acc i l = match l with
|
let rec foldi f acc i l = match l with
|
||||||
| [] -> acc
|
| [] -> acc
|
||||||
| x::l' ->
|
| x::l' ->
|
||||||
let acc = f acc i x in
|
let acc = f acc i x in
|
||||||
foldi f acc (i+1) l'
|
foldi f acc (i+1) l'
|
||||||
in
|
in
|
||||||
foldi f init 0 l
|
foldi f acc 0 l
|
||||||
|
|
||||||
let rec get_at_idx_exn i l = match l with
|
let rec get_at_idx_exn i l = match l with
|
||||||
| [] -> raise Not_found
|
| [] -> raise Not_found
|
||||||
|
|
@ -1019,7 +1018,7 @@ end
|
||||||
module Traverse(M : MONAD) = struct
|
module Traverse(M : MONAD) = struct
|
||||||
open M
|
open M
|
||||||
|
|
||||||
let map_m ~f l =
|
let map_m f l =
|
||||||
let rec aux f acc l = match l with
|
let rec aux f acc l = match l with
|
||||||
| [] -> return (List.rev acc)
|
| [] -> return (List.rev acc)
|
||||||
| x::tail ->
|
| x::tail ->
|
||||||
|
|
@ -1027,23 +1026,23 @@ module Traverse(M : MONAD) = struct
|
||||||
aux f (x' :: acc) tail
|
aux f (x' :: acc) tail
|
||||||
in aux f [] l
|
in aux f [] l
|
||||||
|
|
||||||
let rec map_m_par ~f l = match l with
|
let rec map_m_par f l = match l with
|
||||||
| [] -> M.return []
|
| [] -> M.return []
|
||||||
| x::tl ->
|
| x::tl ->
|
||||||
let x' = f x in
|
let x' = f x in
|
||||||
let tl' = map_m_par ~f tl in
|
let tl' = map_m_par f tl in
|
||||||
x' >>= fun x' ->
|
x' >>= fun x' ->
|
||||||
tl' >>= fun tl' ->
|
tl' >>= fun tl' ->
|
||||||
M.return (x'::tl')
|
M.return (x'::tl')
|
||||||
|
|
||||||
let sequence_m l = map_m l ~f:(fun x->x)
|
let sequence_m l = map_m (fun x->x) l
|
||||||
|
|
||||||
let rec fold_m ~f ~init l = match l with
|
let rec fold_m f acc l = match l with
|
||||||
| [] -> return init
|
| [] -> return acc
|
||||||
| x :: l' ->
|
| x :: l' ->
|
||||||
f init x
|
f acc x
|
||||||
>>= fun acc' ->
|
>>= fun acc' ->
|
||||||
fold_m ~f ~init:acc' l'
|
fold_m f acc' l'
|
||||||
end
|
end
|
||||||
|
|
||||||
(** {2 Conversions} *)
|
(** {2 Conversions} *)
|
||||||
|
|
@ -1055,7 +1054,7 @@ type 'a printer = Format.formatter -> 'a -> unit
|
||||||
type 'a random_gen = Random.State.t -> 'a
|
type 'a random_gen = Random.State.t -> 'a
|
||||||
|
|
||||||
let random_len len g st =
|
let random_len len g st =
|
||||||
init len ~f:(fun _ -> g st)
|
init len (fun _ -> g st)
|
||||||
|
|
||||||
(*$T
|
(*$T
|
||||||
random_len 10 CCInt.random_small (Random.State.make [||]) |> List.length = 10
|
random_len 10 CCInt.random_small (Random.State.make [||]) |> List.length = 10
|
||||||
|
|
@ -1077,7 +1076,7 @@ let random_choose l = match l with
|
||||||
let i = Random.State.int st len in
|
let i = Random.State.int st len in
|
||||||
List.nth l i
|
List.nth l i
|
||||||
|
|
||||||
let random_sequence l st = map l ~f:(fun g -> g st)
|
let random_sequence l st = map (fun g -> g st) l
|
||||||
|
|
||||||
let to_seq l k = List.iter k l
|
let to_seq l k = List.iter k l
|
||||||
let of_seq seq =
|
let of_seq seq =
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ val is_empty : _ t -> bool
|
||||||
(** [is_empty l] returns [true] iff [l = []]
|
(** [is_empty l] returns [true] iff [l = []]
|
||||||
@since 0.11 *)
|
@since 0.11 *)
|
||||||
|
|
||||||
val map : f:('a -> 'b) -> 'a t -> 'b t
|
val map : ('a -> 'b) -> 'a t -> 'b t
|
||||||
(** Safe version of map *)
|
(** Safe version of map *)
|
||||||
|
|
||||||
val (>|=) : 'a t -> ('a -> 'b) -> 'b t
|
val (>|=) : 'a t -> ('a -> 'b) -> 'b t
|
||||||
|
|
@ -32,38 +32,38 @@ val cons_maybe : 'a option -> 'a t -> 'a t
|
||||||
|
|
||||||
val (@) : 'a t -> 'a t -> 'a t
|
val (@) : 'a t -> 'a t -> 'a t
|
||||||
|
|
||||||
val filter : f:('a -> bool) -> 'a t -> 'a t
|
val filter : ('a -> bool) -> 'a t -> 'a t
|
||||||
(** Safe version of {!List.filter} *)
|
(** Safe version of {!List.filter} *)
|
||||||
|
|
||||||
val fold_right : ('a -> 'b -> 'b) -> 'a t -> 'b -> 'b
|
val fold_right : ('a -> 'b -> 'b) -> 'a t -> 'b -> 'b
|
||||||
(** Safe version of [fold_right] *)
|
(** Safe version of [fold_right] *)
|
||||||
|
|
||||||
val fold_while : f:('a -> 'b -> 'a * [`Stop | `Continue]) -> init:'a -> 'b t -> 'a
|
val fold_while : ('a -> 'b -> 'a * [`Stop | `Continue]) -> 'a -> 'b t -> 'a
|
||||||
(** Fold until a stop condition via [('a, `Stop)] is
|
(** Fold until a stop condition via [('a, `Stop)] is
|
||||||
indicated by the accumulator
|
indicated by the accumulator
|
||||||
@since 0.8 *)
|
@since 0.8 *)
|
||||||
|
|
||||||
val fold_map : f:('acc -> 'a -> 'acc * 'b) -> init:'acc -> 'a list -> 'acc * 'b list
|
val fold_map : ('acc -> 'a -> 'acc * 'b) -> 'acc -> 'a list -> 'acc * 'b list
|
||||||
(** [fold_map f acc l] is a [fold_left]-like function, but it also maps the
|
(** [fold_map f acc l] is a [fold_left]-like function, but it also maps the
|
||||||
list to another list.
|
list to another list.
|
||||||
@since 0.14 *)
|
@since 0.14 *)
|
||||||
|
|
||||||
val fold_map2 : f:('acc -> 'a -> 'b -> 'acc * 'c) -> init:'acc -> 'a list -> 'b list -> 'acc * 'c list
|
val fold_map2 : ('acc -> 'a -> 'b -> 'acc * 'c) -> 'acc -> 'a list -> 'b list -> 'acc * 'c list
|
||||||
(** [fold_map2] is to [fold_map] what [List.map2] is to [List.map].
|
(** [fold_map2] is to [fold_map] what [List.map2] is to [List.map].
|
||||||
@raise Invalid_argument if the lists do not have the same length
|
@raise Invalid_argument if the lists do not have the same length
|
||||||
@since 0.16 *)
|
@since 0.16 *)
|
||||||
|
|
||||||
val fold_filter_map : f:('acc -> 'a -> 'acc * 'b option) -> init:'acc -> 'a list -> 'acc * 'b list
|
val fold_filter_map : ('acc -> 'a -> 'acc * 'b option) -> 'acc -> 'a list -> 'acc * 'b list
|
||||||
(** [fold_filter_map f acc l] is a [fold_left]-like function, but also
|
(** [fold_filter_map f acc l] is a [fold_left]-like function, but also
|
||||||
generates a list of output in a way similar to {!filter_map}
|
generates a list of output in a way similar to {!filter_map}
|
||||||
@since 0.17 *)
|
@since 0.17 *)
|
||||||
|
|
||||||
val fold_flat_map : f:('acc -> 'a -> 'acc * 'b list) -> init:'acc -> 'a list -> 'acc * 'b list
|
val fold_flat_map : ('acc -> 'a -> 'acc * 'b list) -> 'acc -> 'a list -> 'acc * 'b list
|
||||||
(** [fold_flat_map f acc l] is a [fold_left]-like function, but it also maps the
|
(** [fold_flat_map f acc l] is a [fold_left]-like function, but it also maps the
|
||||||
list to a list of lists that is then [flatten]'d..
|
list to a list of lists that is then [flatten]'d..
|
||||||
@since 0.14 *)
|
@since 0.14 *)
|
||||||
|
|
||||||
val init : int -> f:(int -> 'a) -> 'a t
|
val init : int -> (int -> 'a) -> 'a t
|
||||||
(** Similar to {!Array.init}
|
(** Similar to {!Array.init}
|
||||||
@since 0.6 *)
|
@since 0.6 *)
|
||||||
|
|
||||||
|
|
@ -71,23 +71,23 @@ val compare : ('a -> 'a -> int) -> 'a t -> 'a t -> int
|
||||||
|
|
||||||
val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> bool
|
val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> bool
|
||||||
|
|
||||||
val flat_map : f:('a -> 'b t) -> 'a t -> 'b t
|
val flat_map : ('a -> 'b t) -> 'a t -> 'b t
|
||||||
(** Map and flatten at the same time (safe). Evaluation order is not guaranteed. *)
|
(** Map and flatten at the same time (safe). Evaluation order is not guaranteed. *)
|
||||||
|
|
||||||
val flatten : 'a t t -> 'a t
|
val flatten : 'a t t -> 'a t
|
||||||
(** Safe flatten *)
|
(** Safe flatten *)
|
||||||
|
|
||||||
val product : f:('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t
|
val product : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t
|
||||||
(** Cartesian product of the two lists, with the given combinator *)
|
(** Cartesian product of the two lists, with the given combinator *)
|
||||||
|
|
||||||
val fold_product : f:('c -> 'a -> 'b -> 'c) -> init:'c -> 'a t -> 'b t -> 'c
|
val fold_product : ('c -> 'a -> 'b -> 'c) -> 'c -> 'a t -> 'b t -> 'c
|
||||||
(** Fold on the cartesian product *)
|
(** Fold on the cartesian product *)
|
||||||
|
|
||||||
val diagonal : 'a t -> ('a * 'a) t
|
val diagonal : 'a t -> ('a * 'a) t
|
||||||
(** All pairs of distinct positions of the list. [list_diagonal l] will
|
(** All pairs of distinct positions of the list. [list_diagonal l] will
|
||||||
return the list of [List.nth i l, List.nth j l] if [i < j]. *)
|
return the list of [List.nth i l, List.nth j l] if [i < j]. *)
|
||||||
|
|
||||||
val partition_map : f:('a -> [<`Left of 'b | `Right of 'c | `Drop]) ->
|
val partition_map : ('a -> [<`Left of 'b | `Right of 'c | `Drop]) ->
|
||||||
'a list -> 'b list * 'c list
|
'a list -> 'b list * 'c list
|
||||||
(** [partition_map f l] maps [f] on [l] and gather results in lists:
|
(** [partition_map f l] maps [f] on [l] and gather results in lists:
|
||||||
- if [f x = `Left y], adds [y] to the first list
|
- if [f x = `Left y], adds [y] to the first list
|
||||||
|
|
@ -120,10 +120,10 @@ val take_drop : int -> 'a t -> 'a t * 'a t
|
||||||
(** [take_drop n l] returns [l1, l2] such that [l1 @ l2 = l] and
|
(** [take_drop n l] returns [l1, l2] such that [l1 @ l2 = l] and
|
||||||
[length l1 = min (length l) n] *)
|
[length l1 = min (length l) n] *)
|
||||||
|
|
||||||
val take_while : f:('a -> bool) -> 'a t -> 'a t
|
val take_while : ('a -> bool) -> 'a t -> 'a t
|
||||||
(** @since 0.13 *)
|
(** @since 0.13 *)
|
||||||
|
|
||||||
val drop_while : f:('a -> bool) -> 'a t -> 'a t
|
val drop_while : ('a -> bool) -> 'a t -> 'a t
|
||||||
(** @since 0.13 *)
|
(** @since 0.13 *)
|
||||||
|
|
||||||
val split : int -> 'a t -> 'a t * 'a t
|
val split : int -> 'a t -> 'a t * 'a t
|
||||||
|
|
@ -142,44 +142,43 @@ val last_opt : 'a t -> 'a option
|
||||||
(** Last element.
|
(** Last element.
|
||||||
@since 0.20 *)
|
@since 0.20 *)
|
||||||
|
|
||||||
val find_pred : f:('a -> bool) -> 'a t -> 'a option
|
val find_pred : ('a -> bool) -> 'a t -> 'a option
|
||||||
(** [find_pred p l] finds the first element of [l] that satisfies [p],
|
(** [find_pred p l] finds the first element of [l] that satisfies [p],
|
||||||
or returns [None] if no element satisfies [p]
|
or returns [None] if no element satisfies [p]
|
||||||
@since 0.11 *)
|
@since 0.11 *)
|
||||||
|
|
||||||
val find_pred_exn : f:('a -> bool) -> 'a t -> 'a
|
val find_pred_exn : ('a -> bool) -> 'a t -> 'a
|
||||||
(** Unsafe version of {!find_pred}
|
(** Unsafe version of {!find_pred}
|
||||||
@raise Not_found if no such element is found
|
@raise Not_found if no such element is found
|
||||||
@since 0.11 *)
|
@since 0.11 *)
|
||||||
|
|
||||||
val find_map : f:('a -> 'b option) -> 'a t -> 'b option
|
val find_map : ('a -> 'b option) -> 'a t -> 'b option
|
||||||
(** [find_map f l] traverses [l], applying [f] to each element. If for
|
(** [find_map f l] traverses [l], applying [f] to each element. If for
|
||||||
some element [x], [f x = Some y], then [Some y] is returned. Otherwise
|
some element [x], [f x = Some y], then [Some y] is returned. Otherwise
|
||||||
the call returns [None]
|
the call returns [None]
|
||||||
@since 0.11 *)
|
@since 0.11 *)
|
||||||
|
|
||||||
(* TODO remove *)
|
val find : ('a -> 'b option) -> 'a list -> 'b option
|
||||||
val find : f:('a -> 'b option) -> 'a list -> 'b option
|
|
||||||
(** @deprecated since 0.11 in favor of {!find_map}, for the name is too confusing *)
|
(** @deprecated since 0.11 in favor of {!find_map}, for the name is too confusing *)
|
||||||
|
|
||||||
val find_mapi : f:(int -> 'a -> 'b option) -> 'a t -> 'b option
|
val find_mapi : (int -> 'a -> 'b option) -> 'a t -> 'b option
|
||||||
(** Like {!find_map}, but also pass the index to the predicate function.
|
(** Like {!find_map}, but also pass the index to the predicate function.
|
||||||
@since 0.11 *)
|
@since 0.11 *)
|
||||||
|
|
||||||
val findi : f:(int -> 'a -> 'b option) -> 'a t -> 'b option
|
val findi : (int -> 'a -> 'b option) -> 'a t -> 'b option
|
||||||
(** @deprecated since 0.11 in favor of {!find_mapi}, name is too confusing
|
(** @deprecated since 0.11 in favor of {!find_mapi}, name is too confusing
|
||||||
@since 0.3.4 *)
|
@since 0.3.4 *)
|
||||||
|
|
||||||
val find_idx : f:('a -> bool) -> 'a t -> (int * 'a) option
|
val find_idx : ('a -> bool) -> 'a t -> (int * 'a) option
|
||||||
(** [find_idx p x] returns [Some (i,x)] where [x] is the [i]-th element of [l],
|
(** [find_idx p x] returns [Some (i,x)] where [x] is the [i]-th element of [l],
|
||||||
and [p x] holds. Otherwise returns [None] *)
|
and [p x] holds. Otherwise returns [None] *)
|
||||||
|
|
||||||
val remove : ?eq:('a -> 'a -> bool) -> key:'a -> 'a t -> 'a t
|
val remove : ?eq:('a -> 'a -> bool) -> x:'a -> 'a t -> 'a t
|
||||||
(** [remove ~key l] removes every instance of [key] from [l]. Tailrec.
|
(** [remove ~x l] removes every instance of [x] from [l]. Tailrec.
|
||||||
@param eq equality function
|
@param eq equality function
|
||||||
@since 0.11 *)
|
@since 0.11 *)
|
||||||
|
|
||||||
val filter_map : f:('a -> 'b option) -> 'a t -> 'b t
|
val filter_map : ('a -> 'b option) -> 'a t -> 'b t
|
||||||
(** Map and remove elements at the same time *)
|
(** Map and remove elements at the same time *)
|
||||||
|
|
||||||
val sorted_merge : ?cmp:('a -> 'a -> int) -> 'a list -> 'a list -> 'a list
|
val sorted_merge : ?cmp:('a -> 'a -> int) -> 'a list -> 'a list -> 'a list
|
||||||
|
|
@ -225,11 +224,11 @@ val group_succ : ?eq:('a -> 'a -> bool) -> 'a list -> 'a list list
|
||||||
|
|
||||||
(** {2 Indices} *)
|
(** {2 Indices} *)
|
||||||
|
|
||||||
val mapi : f:(int -> 'a -> 'b) -> 'a t -> 'b t
|
val mapi : (int -> 'a -> 'b) -> 'a t -> 'b t
|
||||||
|
|
||||||
val iteri : f:(int -> 'a -> unit) -> 'a t -> unit
|
val iteri : (int -> 'a -> unit) -> 'a t -> unit
|
||||||
|
|
||||||
val foldi : f:('b -> int -> 'a -> 'b) -> init:'b -> 'a t -> 'b
|
val foldi : ('b -> int -> 'a -> 'b) -> 'b -> 'a t -> 'b
|
||||||
(** Fold on list, with index *)
|
(** Fold on list, with index *)
|
||||||
|
|
||||||
val get_at_idx : int -> 'a t -> 'a option
|
val get_at_idx : int -> 'a t -> 'a option
|
||||||
|
|
@ -380,11 +379,11 @@ end
|
||||||
module Traverse(M : MONAD) : sig
|
module Traverse(M : MONAD) : sig
|
||||||
val sequence_m : 'a M.t t -> 'a t M.t
|
val sequence_m : 'a M.t t -> 'a t M.t
|
||||||
|
|
||||||
val fold_m : f:('b -> 'a -> 'b M.t) -> init:'b -> 'a t -> 'b M.t
|
val fold_m : ('b -> 'a -> 'b M.t) -> 'b -> 'a t -> 'b M.t
|
||||||
|
|
||||||
val map_m : f:('a -> 'b M.t) -> 'a t -> 'b t M.t
|
val map_m : ('a -> 'b M.t) -> 'a t -> 'b t M.t
|
||||||
|
|
||||||
val map_m_par : f:('a -> 'b M.t) -> 'a t -> 'b t M.t
|
val map_m_par : ('a -> 'b M.t) -> 'a t -> 'b t M.t
|
||||||
(** Same as {!map_m} but [map_m_par f (x::l)] evaluates [f x] and
|
(** Same as {!map_m} but [map_m_par f (x::l)] evaluates [f x] and
|
||||||
[f l] "in parallel" before combining their result (for instance
|
[f l] "in parallel" before combining their result (for instance
|
||||||
in Lwt). *)
|
in Lwt). *)
|
||||||
|
|
|
||||||
1
src/core/CCListLabels.ml
Symbolic link
1
src/core/CCListLabels.ml
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
CCList.ml
|
||||||
441
src/core/CCListLabels.mli
Normal file
441
src/core/CCListLabels.mli
Normal file
|
|
@ -0,0 +1,441 @@
|
||||||
|
|
||||||
|
(* This file is free software, part of containers. See file "license" for more details. *)
|
||||||
|
|
||||||
|
(** {1 complements to list} *)
|
||||||
|
|
||||||
|
type 'a t = 'a list
|
||||||
|
|
||||||
|
val empty : 'a t
|
||||||
|
|
||||||
|
val is_empty : _ t -> bool
|
||||||
|
(** [is_empty l] returns [true] iff [l = []]
|
||||||
|
@since 0.11 *)
|
||||||
|
|
||||||
|
val map : f:('a -> 'b) -> 'a t -> 'b t
|
||||||
|
(** Safe version of map *)
|
||||||
|
|
||||||
|
val (>|=) : 'a t -> ('a -> 'b) -> 'b t
|
||||||
|
(** Infix version of [map] with reversed arguments
|
||||||
|
@since 0.5 *)
|
||||||
|
|
||||||
|
val cons : 'a -> 'a t -> 'a t
|
||||||
|
(** [cons x l] is [x::l]
|
||||||
|
@since 0.12 *)
|
||||||
|
|
||||||
|
val append : 'a t -> 'a t -> 'a t
|
||||||
|
(** Safe version of append *)
|
||||||
|
|
||||||
|
val cons_maybe : 'a option -> 'a t -> 'a t
|
||||||
|
(** [cons_maybe (Some x) l] is [x :: l]
|
||||||
|
[cons_maybe None l] is [l]
|
||||||
|
@since 0.13 *)
|
||||||
|
|
||||||
|
val (@) : 'a t -> 'a t -> 'a t
|
||||||
|
|
||||||
|
val filter : f:('a -> bool) -> 'a t -> 'a t
|
||||||
|
(** Safe version of {!List.filter} *)
|
||||||
|
|
||||||
|
val fold_right : ('a -> 'b -> 'b) -> 'a t -> 'b -> 'b
|
||||||
|
(** Safe version of [fold_right] *)
|
||||||
|
|
||||||
|
val fold_while : f:('a -> 'b -> 'a * [`Stop | `Continue]) -> init:'a -> 'b t -> 'a
|
||||||
|
(** Fold until a stop condition via [('a, `Stop)] is
|
||||||
|
indicated by the accumulator
|
||||||
|
@since 0.8 *)
|
||||||
|
|
||||||
|
val fold_map : f:('acc -> 'a -> 'acc * 'b) -> init:'acc -> 'a list -> 'acc * 'b list
|
||||||
|
(** [fold_map f acc l] is a [fold_left]-like function, but it also maps the
|
||||||
|
list to another list.
|
||||||
|
@since 0.14 *)
|
||||||
|
|
||||||
|
val fold_map2 : f:('acc -> 'a -> 'b -> 'acc * 'c) -> init:'acc -> 'a list -> 'b list -> 'acc * 'c list
|
||||||
|
(** [fold_map2] is to [fold_map] what [List.map2] is to [List.map].
|
||||||
|
@raise Invalid_argument if the lists do not have the same length
|
||||||
|
@since 0.16 *)
|
||||||
|
|
||||||
|
val fold_filter_map : f:('acc -> 'a -> 'acc * 'b option) -> init:'acc -> 'a list -> 'acc * 'b list
|
||||||
|
(** [fold_filter_map f acc l] is a [fold_left]-like function, but also
|
||||||
|
generates a list of output in a way similar to {!filter_map}
|
||||||
|
@since 0.17 *)
|
||||||
|
|
||||||
|
val fold_flat_map : f:('acc -> 'a -> 'acc * 'b list) -> init:'acc -> 'a list -> 'acc * 'b list
|
||||||
|
(** [fold_flat_map f acc l] is a [fold_left]-like function, but it also maps the
|
||||||
|
list to a list of lists that is then [flatten]'d..
|
||||||
|
@since 0.14 *)
|
||||||
|
|
||||||
|
val init : int -> f:(int -> 'a) -> 'a t
|
||||||
|
(** Similar to {!Array.init}
|
||||||
|
@since 0.6 *)
|
||||||
|
|
||||||
|
val compare : ('a -> 'a -> int) -> 'a t -> 'a t -> int
|
||||||
|
|
||||||
|
val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> bool
|
||||||
|
|
||||||
|
val flat_map : f:('a -> 'b t) -> 'a t -> 'b t
|
||||||
|
(** Map and flatten at the same time (safe). Evaluation order is not guaranteed. *)
|
||||||
|
|
||||||
|
val flatten : 'a t t -> 'a t
|
||||||
|
(** Safe flatten *)
|
||||||
|
|
||||||
|
val product : f:('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t
|
||||||
|
(** Cartesian product of the two lists, with the given combinator *)
|
||||||
|
|
||||||
|
val fold_product : f:('c -> 'a -> 'b -> 'c) -> init:'c -> 'a t -> 'b t -> 'c
|
||||||
|
(** Fold on the cartesian product *)
|
||||||
|
|
||||||
|
val diagonal : 'a t -> ('a * 'a) t
|
||||||
|
(** All pairs of distinct positions of the list. [list_diagonal l] will
|
||||||
|
return the list of [List.nth i l, List.nth j l] if [i < j]. *)
|
||||||
|
|
||||||
|
val partition_map : f:('a -> [<`Left of 'b | `Right of 'c | `Drop]) ->
|
||||||
|
'a list -> 'b list * 'c list
|
||||||
|
(** [partition_map f l] maps [f] on [l] and gather results in lists:
|
||||||
|
- if [f x = `Left y], adds [y] to the first list
|
||||||
|
- if [f x = `Right z], adds [z] to the second list
|
||||||
|
- if [f x = `Drop], ignores [x]
|
||||||
|
@since 0.11 *)
|
||||||
|
|
||||||
|
val pure : 'a -> 'a t
|
||||||
|
|
||||||
|
val (<*>) : ('a -> 'b) t -> 'a t -> 'b t
|
||||||
|
|
||||||
|
val (<$>) : ('a -> 'b) -> 'a t -> 'b t
|
||||||
|
|
||||||
|
val return : 'a -> 'a t
|
||||||
|
|
||||||
|
val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
|
||||||
|
|
||||||
|
val take : int -> 'a t -> 'a t
|
||||||
|
(** Take the [n] first elements, drop the rest *)
|
||||||
|
|
||||||
|
val drop : int -> 'a t -> 'a t
|
||||||
|
(** Drop the [n] first elements, keep the rest *)
|
||||||
|
|
||||||
|
val hd_tl : 'a t -> 'a * 'a t
|
||||||
|
(** [hd_tl (x :: l)] returns [hd, l].
|
||||||
|
@raise Failure if the list is empty
|
||||||
|
@since 0.16 *)
|
||||||
|
|
||||||
|
val take_drop : int -> 'a t -> 'a t * 'a t
|
||||||
|
(** [take_drop n l] returns [l1, l2] such that [l1 @ l2 = l] and
|
||||||
|
[length l1 = min (length l) n] *)
|
||||||
|
|
||||||
|
val take_while : f:('a -> bool) -> 'a t -> 'a t
|
||||||
|
(** @since 0.13 *)
|
||||||
|
|
||||||
|
val drop_while : f:('a -> bool) -> 'a t -> 'a t
|
||||||
|
(** @since 0.13 *)
|
||||||
|
|
||||||
|
val split : int -> 'a t -> 'a t * 'a t
|
||||||
|
(** Synonym to {!take_drop}
|
||||||
|
@deprecated since 0.13: conflict with the {!List.split} standard function *)
|
||||||
|
|
||||||
|
val last : int -> 'a t -> 'a t
|
||||||
|
(** [last n l] takes the last [n] elements of [l] (or less if
|
||||||
|
[l] doesn't have that many elements *)
|
||||||
|
|
||||||
|
val head_opt : 'a t -> 'a option
|
||||||
|
(** First element.
|
||||||
|
@since 0.20 *)
|
||||||
|
|
||||||
|
val last_opt : 'a t -> 'a option
|
||||||
|
(** Last element.
|
||||||
|
@since 0.20 *)
|
||||||
|
|
||||||
|
val find_pred : f:('a -> bool) -> 'a t -> 'a option
|
||||||
|
(** [find_pred p l] finds the first element of [l] that satisfies [p],
|
||||||
|
or returns [None] if no element satisfies [p]
|
||||||
|
@since 0.11 *)
|
||||||
|
|
||||||
|
val find_pred_exn : f:('a -> bool) -> 'a t -> 'a
|
||||||
|
(** Unsafe version of {!find_pred}
|
||||||
|
@raise Not_found if no such element is found
|
||||||
|
@since 0.11 *)
|
||||||
|
|
||||||
|
val find_map : f:('a -> 'b option) -> 'a t -> 'b option
|
||||||
|
(** [find_map f l] traverses [l], applying [f] to each element. If for
|
||||||
|
some element [x], [f x = Some y], then [Some y] is returned. Otherwise
|
||||||
|
the call returns [None]
|
||||||
|
@since 0.11 *)
|
||||||
|
|
||||||
|
(* TODO remove *)
|
||||||
|
val find : f:('a -> 'b option) -> 'a list -> 'b option
|
||||||
|
(** @deprecated since 0.11 in favor of {!find_map}, for the name is too confusing *)
|
||||||
|
|
||||||
|
val find_mapi : f:(int -> 'a -> 'b option) -> 'a t -> 'b option
|
||||||
|
(** Like {!find_map}, but also pass the index to the predicate function.
|
||||||
|
@since 0.11 *)
|
||||||
|
|
||||||
|
val findi : f:(int -> 'a -> 'b option) -> 'a t -> 'b option
|
||||||
|
(** @deprecated since 0.11 in favor of {!find_mapi}, name is too confusing
|
||||||
|
@since 0.3.4 *)
|
||||||
|
|
||||||
|
val find_idx : f:('a -> bool) -> 'a t -> (int * 'a) option
|
||||||
|
(** [find_idx p x] returns [Some (i,x)] where [x] is the [i]-th element of [l],
|
||||||
|
and [p x] holds. Otherwise returns [None] *)
|
||||||
|
|
||||||
|
val remove : ?eq:('a -> 'a -> bool) -> key:'a -> 'a t -> 'a t
|
||||||
|
(** [remove ~key l] removes every instance of [key] from [l]. Tailrec.
|
||||||
|
@param eq equality function
|
||||||
|
@since 0.11 *)
|
||||||
|
|
||||||
|
val filter_map : f:('a -> 'b option) -> 'a t -> 'b t
|
||||||
|
(** Map and remove elements at the same time *)
|
||||||
|
|
||||||
|
val sorted_merge : ?cmp:('a -> 'a -> int) -> 'a list -> 'a list -> 'a list
|
||||||
|
(** Merges elements from both sorted list *)
|
||||||
|
|
||||||
|
val sort_uniq : ?cmp:('a -> 'a -> int) -> 'a list -> 'a list
|
||||||
|
(** Sort the list and remove duplicate elements *)
|
||||||
|
|
||||||
|
val sorted_merge_uniq : ?cmp:('a -> 'a -> int) -> 'a list -> 'a list -> 'a list
|
||||||
|
(** [sorted_merge_uniq l1 l2] merges the sorted lists [l1] and [l2] and
|
||||||
|
removes duplicates
|
||||||
|
@since 0.10 *)
|
||||||
|
|
||||||
|
val is_sorted : ?cmp:('a -> 'a -> int) -> 'a list -> bool
|
||||||
|
(** [is_sorted l] returns [true] iff [l] is sorted (according to given order)
|
||||||
|
@param cmp the comparison function (default [Pervasives.compare])
|
||||||
|
@since 0.17 *)
|
||||||
|
|
||||||
|
val sorted_insert : ?cmp:('a -> 'a -> int) -> ?uniq:bool -> 'a -> 'a list -> 'a list
|
||||||
|
(** [sorted_insert x l] inserts [x] into [l] such that, if [l] was sorted,
|
||||||
|
then [sorted_insert x l] is sorted too.
|
||||||
|
@param uniq if true and [x] is already in sorted position in [l], then
|
||||||
|
[x] is not duplicated. Default [false] ([x] will be inserted in any case).
|
||||||
|
@since 0.17 *)
|
||||||
|
|
||||||
|
(*$Q
|
||||||
|
Q.(pair small_int (list small_int)) (fun (x,l) -> \
|
||||||
|
let l = List.sort Pervasives.compare l in \
|
||||||
|
is_sorted (sorted_insert x l))
|
||||||
|
*)
|
||||||
|
|
||||||
|
val uniq_succ : ?eq:('a -> 'a -> bool) -> 'a list -> 'a list
|
||||||
|
(** [uniq_succ l] removes duplicate elements that occur one next to the other.
|
||||||
|
Examples:
|
||||||
|
[uniq_succ [1;2;1] = [1;2;1]]
|
||||||
|
[uniq_succ [1;1;2] = [1;2]]
|
||||||
|
@since 0.10 *)
|
||||||
|
|
||||||
|
val group_succ : ?eq:('a -> 'a -> bool) -> 'a list -> 'a list list
|
||||||
|
(** [group_succ ~eq l] groups together consecutive elements that are equal
|
||||||
|
according to [eq]
|
||||||
|
@since 0.11 *)
|
||||||
|
|
||||||
|
(** {2 Indices} *)
|
||||||
|
|
||||||
|
val mapi : f:(int -> 'a -> 'b) -> 'a t -> 'b t
|
||||||
|
|
||||||
|
val iteri : f:(int -> 'a -> unit) -> 'a t -> unit
|
||||||
|
|
||||||
|
val foldi : f:('b -> int -> 'a -> 'b) -> init:'b -> 'a t -> 'b
|
||||||
|
(** Fold on list, with index *)
|
||||||
|
|
||||||
|
val get_at_idx : int -> 'a t -> 'a option
|
||||||
|
|
||||||
|
val get_at_idx_exn : int -> 'a t -> 'a
|
||||||
|
(** Get the i-th element, or
|
||||||
|
@raise Not_found if the index is invalid *)
|
||||||
|
|
||||||
|
val set_at_idx : int -> 'a -> 'a t -> 'a t
|
||||||
|
(** Set i-th element (removes the old one), or does nothing if
|
||||||
|
index is too high *)
|
||||||
|
|
||||||
|
val insert_at_idx : int -> 'a -> 'a t -> 'a t
|
||||||
|
(** Insert at i-th position, between the two existing elements. If the
|
||||||
|
index is too high, append at the end of the list *)
|
||||||
|
|
||||||
|
val remove_at_idx : int -> 'a t -> 'a t
|
||||||
|
(** Remove element at given index. Does nothing if the index is
|
||||||
|
too high. *)
|
||||||
|
|
||||||
|
(** {2 Set Operators}
|
||||||
|
|
||||||
|
Those operations maintain the invariant that the list does not
|
||||||
|
contain duplicates (if it already satisfies it) *)
|
||||||
|
|
||||||
|
val add_nodup : ?eq:('a -> 'a -> bool) -> 'a -> 'a t -> 'a t
|
||||||
|
(** [add_nodup x set] adds [x] to [set] if it was not already present. Linear time.
|
||||||
|
@since 0.11 *)
|
||||||
|
|
||||||
|
val remove_one : ?eq:('a -> 'a -> bool) -> 'a -> 'a t -> 'a t
|
||||||
|
(** [remove_one x set] removes one occurrence of [x] from [set]. Linear time.
|
||||||
|
@since 0.11 *)
|
||||||
|
|
||||||
|
val mem : ?eq:('a -> 'a -> bool) -> 'a -> 'a t -> bool
|
||||||
|
(** Membership to the list. Linear time *)
|
||||||
|
|
||||||
|
val subset : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t -> bool
|
||||||
|
(** Test for inclusion *)
|
||||||
|
|
||||||
|
val uniq : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t
|
||||||
|
(** Remove duplicates w.r.t the equality predicate.
|
||||||
|
Complexity is quadratic in the length of the list, but the order
|
||||||
|
of elements is preserved. If you wish for a faster de-duplication
|
||||||
|
but do not care about the order, use {!sort_uniq}*)
|
||||||
|
|
||||||
|
val union : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t -> 'a t
|
||||||
|
(** List union. Complexity is product of length of inputs. *)
|
||||||
|
|
||||||
|
val inter : ?eq:('a -> 'a -> bool) -> 'a t -> 'a t -> 'a t
|
||||||
|
(** List intersection. Complexity is product of length of inputs. *)
|
||||||
|
|
||||||
|
(** {2 Other Constructors} *)
|
||||||
|
|
||||||
|
val range_by : step:int -> int -> int -> int t
|
||||||
|
(** [range_by ~step i j] iterates on integers from [i] to [j] included,
|
||||||
|
where the difference between successive elements is [step].
|
||||||
|
use a negative [step] for a decreasing list.
|
||||||
|
@raise Invalid_argument if [step=0]
|
||||||
|
@since 0.18 *)
|
||||||
|
|
||||||
|
val range : int -> int -> int t
|
||||||
|
(** [range i j] iterates on integers from [i] to [j] included . It works
|
||||||
|
both for decreasing and increasing ranges *)
|
||||||
|
|
||||||
|
val range' : int -> int -> int t
|
||||||
|
(** Same as {!range} but the second bound is excluded.
|
||||||
|
For instance [range' 0 5 = [0;1;2;3;4]] *)
|
||||||
|
|
||||||
|
val (--) : int -> int -> int t
|
||||||
|
(** Infix alias for [range] *)
|
||||||
|
|
||||||
|
val (--^) : int -> int -> int t
|
||||||
|
(** Infix alias for [range']
|
||||||
|
@since 0.17 *)
|
||||||
|
|
||||||
|
val replicate : int -> 'a -> 'a t
|
||||||
|
(** Replicate the given element [n] times *)
|
||||||
|
|
||||||
|
val repeat : int -> 'a t -> 'a t
|
||||||
|
(** Concatenate the list with itself [n] times *)
|
||||||
|
|
||||||
|
(** {2 Association Lists} *)
|
||||||
|
|
||||||
|
module Assoc : sig
|
||||||
|
type ('a, 'b) t = ('a*'b) list
|
||||||
|
|
||||||
|
val get : ?eq:('a->'a->bool) -> 'a -> ('a,'b) t -> 'b option
|
||||||
|
(** Find the element *)
|
||||||
|
|
||||||
|
val get_exn : ?eq:('a->'a->bool) -> 'a -> ('a,'b) t -> 'b
|
||||||
|
(** Same as [get], but unsafe
|
||||||
|
@raise Not_found if the element is not present *)
|
||||||
|
|
||||||
|
val set : ?eq:('a->'a->bool) -> 'a -> 'b -> ('a,'b) t -> ('a,'b) t
|
||||||
|
(** Add the binding into the list (erase it if already present) *)
|
||||||
|
|
||||||
|
val mem : ?eq:('a->'a->bool) -> 'a -> ('a,_) t -> bool
|
||||||
|
(** [mem x l] returns [true] iff [x] is a key in [l]
|
||||||
|
@since 0.16 *)
|
||||||
|
|
||||||
|
val update :
|
||||||
|
?eq:('a->'a->bool) -> f:('b option -> 'b option) -> 'a -> ('a,'b) t -> ('a,'b) t
|
||||||
|
(** [update k ~f l] updates [l] on the key [k], by calling [f (get l k)]
|
||||||
|
and removing [k] if it returns [None], mapping [k] to [v'] if it
|
||||||
|
returns [Some v']
|
||||||
|
@since 0.16 *)
|
||||||
|
|
||||||
|
val remove : ?eq:('a->'a->bool) -> 'a -> ('a,'b) t -> ('a,'b) t
|
||||||
|
(** [remove x l] removes the first occurrence of [k] from [l].
|
||||||
|
@since 0.17 *)
|
||||||
|
end
|
||||||
|
|
||||||
|
(** {2 References on Lists}
|
||||||
|
@since 0.3.3 *)
|
||||||
|
|
||||||
|
module Ref : sig
|
||||||
|
type 'a t = 'a list ref
|
||||||
|
|
||||||
|
val push : 'a t -> 'a -> unit
|
||||||
|
|
||||||
|
val pop : 'a t -> 'a option
|
||||||
|
|
||||||
|
val pop_exn : 'a t -> 'a
|
||||||
|
(** Unsafe version of {!pop}.
|
||||||
|
@raise Failure if the list is empty *)
|
||||||
|
|
||||||
|
val create : unit -> 'a t
|
||||||
|
(** Create a new list reference *)
|
||||||
|
|
||||||
|
val clear : _ t -> unit
|
||||||
|
(** Remove all elements *)
|
||||||
|
|
||||||
|
val lift : ('a list -> 'b) -> 'a t -> 'b
|
||||||
|
(** Apply a list function to the content *)
|
||||||
|
|
||||||
|
val push_list : 'a t -> 'a list -> unit
|
||||||
|
(** Add elements of the list at the beginning of the list ref. Elements
|
||||||
|
at the end of the list will be at the beginning of the list ref *)
|
||||||
|
end
|
||||||
|
|
||||||
|
(** {2 Monadic Operations} *)
|
||||||
|
module type MONAD = sig
|
||||||
|
type 'a t
|
||||||
|
val return : 'a -> 'a t
|
||||||
|
val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
|
||||||
|
end
|
||||||
|
|
||||||
|
module Traverse(M : MONAD) : sig
|
||||||
|
val sequence_m : 'a M.t t -> 'a t M.t
|
||||||
|
|
||||||
|
val fold_m : f:('b -> 'a -> 'b M.t) -> init:'b -> 'a t -> 'b M.t
|
||||||
|
|
||||||
|
val map_m : f:('a -> 'b M.t) -> 'a t -> 'b t M.t
|
||||||
|
|
||||||
|
val map_m_par : f:('a -> 'b M.t) -> 'a t -> 'b t M.t
|
||||||
|
(** Same as {!map_m} but [map_m_par f (x::l)] evaluates [f x] and
|
||||||
|
[f l] "in parallel" before combining their result (for instance
|
||||||
|
in Lwt). *)
|
||||||
|
end
|
||||||
|
|
||||||
|
(** {2 Conversions} *)
|
||||||
|
|
||||||
|
type 'a sequence = ('a -> unit) -> unit
|
||||||
|
type 'a gen = unit -> 'a option
|
||||||
|
type 'a klist = unit -> [`Nil | `Cons of 'a * 'a klist]
|
||||||
|
type 'a printer = Format.formatter -> 'a -> unit
|
||||||
|
type 'a random_gen = Random.State.t -> 'a
|
||||||
|
|
||||||
|
val random : 'a random_gen -> 'a t random_gen
|
||||||
|
val random_non_empty : 'a random_gen -> 'a t random_gen
|
||||||
|
val random_len : int -> 'a random_gen -> 'a t random_gen
|
||||||
|
|
||||||
|
val random_choose : 'a t -> 'a random_gen
|
||||||
|
(** Randomly choose an element in the list.
|
||||||
|
@raise Not_found if the list is empty *)
|
||||||
|
|
||||||
|
val random_sequence : 'a random_gen t -> 'a t random_gen
|
||||||
|
|
||||||
|
val to_seq : 'a t -> 'a sequence
|
||||||
|
val of_seq : 'a sequence -> 'a t
|
||||||
|
|
||||||
|
val to_gen : 'a t -> 'a gen
|
||||||
|
val of_gen : 'a gen -> 'a t
|
||||||
|
|
||||||
|
val to_klist : 'a t -> 'a klist
|
||||||
|
val of_klist : 'a klist -> 'a t
|
||||||
|
|
||||||
|
(** {2 Infix Operators}
|
||||||
|
It is convenient to {!open CCList.Infix} to access the infix operators
|
||||||
|
without cluttering the scope too much.
|
||||||
|
|
||||||
|
@since 0.16 *)
|
||||||
|
|
||||||
|
module Infix : sig
|
||||||
|
val (>|=) : 'a t -> ('a -> 'b) -> 'b t
|
||||||
|
val (@) : 'a t -> 'a t -> 'a t
|
||||||
|
val (<*>) : ('a -> 'b) t -> 'a t -> 'b t
|
||||||
|
val (<$>) : ('a -> 'b) -> 'a t -> 'b t
|
||||||
|
val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
|
||||||
|
val (--) : int -> int -> int t
|
||||||
|
|
||||||
|
val (--^) : int -> int -> int t
|
||||||
|
(** @since 0.17 *)
|
||||||
|
end
|
||||||
|
|
||||||
|
(** {2 IO} *)
|
||||||
|
|
||||||
|
val pp : ?start:string -> ?stop:string -> ?sep:string ->
|
||||||
|
'a printer -> 'a t printer
|
||||||
|
|
@ -604,7 +604,7 @@ module Make(Key : KEY)
|
||||||
aux acc t
|
aux acc t
|
||||||
|
|
||||||
(*$T
|
(*$T
|
||||||
let l = CCList.(1 -- 10 |> map ~f:(fun x->x,x)) in \
|
let l = CCList.(1 -- 10 |> map (fun x->x,x)) in \
|
||||||
M.of_list l \
|
M.of_list l \
|
||||||
|> M.fold ~f:(fun acc x y -> (x,y)::acc) ~x:[] \
|
|> M.fold ~f:(fun acc x y -> (x,y)::acc) ~x:[] \
|
||||||
|> List.sort Pervasives.compare = l
|
|> List.sort Pervasives.compare = l
|
||||||
|
|
@ -720,7 +720,7 @@ module Make(Key : KEY)
|
||||||
end
|
end
|
||||||
|
|
||||||
(*$R
|
(*$R
|
||||||
let m = M.of_list CCList.( (501 -- 1000) @ (500 -- 1) |> map ~f:(fun i->i,i)) in
|
let m = M.of_list CCList.( (501 -- 1000) @ (500 -- 1) |> map (fun i->i,i)) in
|
||||||
assert_equal ~printer:CCInt.to_string 1000 (M.cardinal m);
|
assert_equal ~printer:CCInt.to_string 1000 (M.cardinal m);
|
||||||
assert_bool "check all get"
|
assert_bool "check all get"
|
||||||
(Sequence.for_all (fun i -> i = M.get_exn i m) Sequence.(1 -- 1000));
|
(Sequence.for_all (fun i -> i = M.get_exn i m) Sequence.(1 -- 1000));
|
||||||
|
|
|
||||||
|
|
@ -361,7 +361,7 @@ module MakeFull(K : KEY) : S with type key = K.t = struct
|
||||||
with Not_found -> None
|
with Not_found -> None
|
||||||
|
|
||||||
(*$T
|
(*$T
|
||||||
let m = CCList.(0 -- 1000 |> map ~f:(fun i->i,i) |> M.of_list) in \
|
let m = CCList.(0 -- 1000 |> map (fun i->i,i) |> M.of_list) in \
|
||||||
List.for_all (fun i -> M.nth_exn i m = (i,i)) CCList.(0--1000)
|
List.for_all (fun i -> M.nth_exn i m = (i,i)) CCList.(0--1000)
|
||||||
*)
|
*)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue