add init,fold_map,fold_filter_map,sorted,diagonal,findi,…

This commit is contained in:
Simon Cruanes 2016-12-26 00:45:03 +01:00
parent b062ccfd70
commit 4748655708
3 changed files with 159 additions and 0 deletions

View file

@ -48,6 +48,17 @@ let repeat x k = while true do k x done
(seq |> take 3 |> to_list); (seq |> take 3 |> to_list);
*) *)
let init f yield =
let rec aux i =
yield (f i);
aux (i+1)
in
aux 0
(*$=
[0;1;2;3;4] (init (fun x->x) |> take 5 |> to_list)
*)
let rec iterate f x k = let rec iterate f x k =
k x; k x;
iterate f (f x) k iterate f (f x) k
@ -94,6 +105,28 @@ let foldi f init seq =
OUnit.assert_equal [1, "world"; 0, "hello"] l; OUnit.assert_equal [1, "world"; 0, "hello"] l;
*) *)
let fold_map f init seq yield =
let r = ref init in
seq
(fun x ->
let acc', y = f !r x in
r := acc';
yield y)
(*$= & ~printer:Q.Print.(list int)
[0;1;3;5] (0--3 |> fold_map (fun prev x -> x,prev+x) 0 |> to_list)
*)
let fold_filter_map f init seq yield =
let r = ref init in
seq
(fun x ->
let acc', y = f !r x in
r := acc';
match y with
| None -> ()
| Some y' -> yield y')
let map f seq k = seq (fun x -> k (f x)) let map f seq k = seq (fun x -> k (f x))
let mapi f seq k = let mapi f seq k =
@ -320,6 +353,23 @@ let sort ?(cmp=Pervasives.compare) seq =
|> OUnit.assert_equal [100;99;98;97] |> OUnit.assert_equal [100;99;98;97]
*) *)
exception Exit_sorted
let sorted ?(cmp=Pervasives.compare) seq =
let prev = ref None in
try
seq (fun x -> match !prev with
| Some y when cmp y x > 0 -> raise Exit_sorted
| _ -> prev := Some x);
true
with Exit_sorted -> false
(*$T
of_list [1;2;3;4] |> sorted
not (of_list [1;2;3;0;4] |> sorted)
sorted empty
*)
let group_succ_by ?(eq=fun x y -> x = y) seq k = let group_succ_by ?(eq=fun x y -> x = y) seq k =
let cur = ref [] in let cur = ref [] in
seq (fun x -> seq (fun x ->
@ -413,6 +463,16 @@ let product outer inner k =
let product2 outer inner k = let product2 outer inner k =
outer (fun x -> inner (fun y -> k x y)) outer (fun x -> inner (fun y -> k x y))
let rec diagonal l yield = match l with
| [] -> ()
| x::tail ->
List.iter (fun y -> yield (x,y)) tail;
diagonal tail yield
(*$=
[0,1; 0,2; 1,2] (diagonal [0;1;2] |> to_list)
*)
let join ~join_row s1 s2 k = let join ~join_row s1 s2 k =
s1 (fun a -> s1 (fun a ->
s2 (fun b -> s2 (fun b ->
@ -607,6 +667,25 @@ let find f seq =
end; end;
!r !r
let findi f seq =
let i = ref 0 in
let r = ref None in
begin
try
seq
(fun x -> match f !i x with
| None -> incr i
| Some _ as res -> r := res; raise ExitFind);
with ExitFind -> ()
end;
!r
let find_pred f seq = find (fun x -> if f x then Some x else None) seq
let find_pred_exn f seq = match find_pred f seq with
| Some x -> x
| None -> raise Not_found
let length seq = let length seq =
let r = ref 0 in let r = ref 0 in
seq (fun _ -> incr r); seq (fun _ -> incr r);

View file

@ -57,6 +57,10 @@ val singleton : 'a -> 'a t
val doubleton : 'a -> 'a -> 'a t val doubleton : 'a -> 'a -> 'a t
(** Sequence with exactly two elements *) (** Sequence with exactly two elements *)
val init : (int -> 'a) -> 'a t
(** [init f] is the infinite sequence [f 0; f 1; f 2; …].
@since NEXT_RELEASE *)
val cons : 'a -> 'a t -> 'a t val cons : 'a -> 'a t -> 'a t
(** [cons x l] yields [x], then yields from [l]. (** [cons x l] yields [x], then yields from [l].
Same as [append (singleton x) l] *) Same as [append (singleton x) l] *)
@ -103,6 +107,17 @@ val fold : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a
val foldi : ('a -> int -> 'b -> 'a) -> 'a -> 'b t -> 'a val foldi : ('a -> int -> 'b -> 'a) -> 'a -> 'b t -> 'a
(** Fold over elements of the sequence and their index, consuming it *) (** Fold over elements of the sequence and their index, consuming it *)
val fold_map : ('acc -> 'a -> 'acc * 'b) -> 'acc -> 'a t -> 'b t
(** [fold_map f acc l] is like {!map}, but it carries some state as in
{!fold}. The state is not returned, it is just used to thread some
information to the map function.
@since NEXT_RELEASE *)
val fold_filter_map : ('acc -> 'a -> 'acc * 'b option) -> 'acc -> 'a t -> 'b t
(** [fold_filter_map f acc l] is a {!fold_map}-like function, but the
function can choose to skip an element by retuning [None].
@since NEXT_RELEASE *)
val map : ('a -> 'b) -> 'a t -> 'b t val map : ('a -> 'b) -> 'a t -> 'b t
(** Map objects of the sequence into other elements, lazily *) (** Map objects of the sequence into other elements, lazily *)
@ -129,6 +144,20 @@ val find : ('a -> 'b option) -> 'a t -> 'b option
(** Find the first element on which the function doesn't return [None] (** Find the first element on which the function doesn't return [None]
@since 0.5 *) @since 0.5 *)
val findi : (int -> 'a -> 'b option) -> 'a t -> 'b option
(** Indexed version of {!find}
@since NEXT_RELEASE *)
val find_pred : ('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 NEXT_RELEASE *)
val find_pred_exn : ('a -> bool) -> 'a t -> 'a
(** Unsafe version of {!find_pred}
@raise Not_found if no such element is found
@since NEXT_RELEASE *)
val length : 'a t -> int val length : 'a t -> int
(** How long is the sequence? Forces the sequence. *) (** How long is the sequence? Forces the sequence. *)
@ -197,6 +226,10 @@ val sort : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t
val sort_uniq : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t val sort_uniq : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t
(** Sort the sequence and remove duplicates. Eager, same as [sort] *) (** Sort the sequence and remove duplicates. Eager, same as [sort] *)
val sorted : ?cmp:('a -> 'a -> int) -> 'a t -> bool
(** Checks whether the sequence is sorted. Eager, same as {!sort}.
@since NEXT_RELEASE *)
val group_succ_by : ?eq:('a -> 'a -> bool) -> 'a t -> 'a list t val group_succ_by : ?eq:('a -> 'a -> bool) -> 'a t -> 'a list t
(** Group equal consecutive elements. (** Group equal consecutive elements.
Formerly synonym to [group]. Formerly synonym to [group].
@ -218,6 +251,11 @@ val product : 'a t -> 'b t -> ('a * 'b) t
as required (several times), possibly by calling {!persistent} on it as required (several times), possibly by calling {!persistent} on it
beforehand. *) beforehand. *)
val diagonal : 'a list -> ('a * 'a) t
(** All pairs of distinct positions of the list. [diagonal l] will
return the list of [List.nth i l, List.nth j l] if [i < j].
@since NEXT_RELEASE *)
val product2 : 'a t -> 'b t -> ('a, 'b) t2 val product2 : 'a t -> 'b t -> ('a, 'b) t2
(** Binary version of {!product}. Same requirements. (** Binary version of {!product}. Same requirements.
@since 0.5 *) @since 0.5 *)

View file

@ -35,6 +35,10 @@ val singleton : 'a -> 'a t
val doubleton : 'a -> 'a -> 'a t val doubleton : 'a -> 'a -> 'a t
(** Sequence with exactly two elements *) (** Sequence with exactly two elements *)
val init : f:(int -> 'a) -> 'a t
(** [init f] is the infinite sequence [f 0; f 1; f 2; …].
@since NEXT_RELEASE *)
val cons : 'a -> 'a t -> 'a t val cons : 'a -> 'a t -> 'a t
(** [cons x l] yields [x], then yields from [l]. (** [cons x l] yields [x], then yields from [l].
Same as [append (singleton x) l] *) Same as [append (singleton x) l] *)
@ -81,6 +85,17 @@ val fold : f:('a -> 'b -> 'a) -> init:'a -> 'b t -> 'a
val foldi : f:('a -> int -> 'b -> 'a) -> init:'a -> 'b t -> 'a val foldi : f:('a -> int -> 'b -> 'a) -> init:'a -> 'b t -> 'a
(** Fold over elements of the sequence and their index, consuming it *) (** Fold over elements of the sequence and their index, consuming it *)
val fold_map : f:('acc -> 'a -> 'acc * 'b) -> init:'acc -> 'a t -> 'b t
(** [fold_map f acc l] is like {!map}, but it carries some state as in
{!fold}. The state is not returned, it is just used to thread some
information to the map function.
@since NEXT_RELEASE *)
val fold_filter_map : f:('acc -> 'a -> 'acc * 'b option) -> init:'acc -> 'a t -> 'b t
(** [fold_filter_map f acc l] is a {!fold_map}-like function, but the
function can choose to skip an element by retuning [None].
@since NEXT_RELEASE *)
val map : f:('a -> 'b) -> 'a t -> 'b t val map : f:('a -> 'b) -> 'a t -> 'b t
(** Map objects of the sequence into other elements, lazily *) (** Map objects of the sequence into other elements, lazily *)
@ -105,6 +120,20 @@ val mem : ?eq:('a -> 'a -> bool) -> x:'a -> 'a t -> bool
val find : f:('a -> 'b option) -> 'a t -> 'b option val find : f:('a -> 'b option) -> 'a t -> 'b option
(** Find the first element on which the function doesn't return [None] *) (** Find the first element on which the function doesn't return [None] *)
val findi : f:(int -> 'a -> 'b option) -> 'a t -> 'b option
(** Indexed version of {!find}
@since NEXT_RELEASE *)
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 NEXT_RELEASE *)
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 NEXT_RELEASE *)
val length : 'a t -> int val length : 'a t -> int
(** How long is the sequence? Forces the sequence. *) (** How long is the sequence? Forces the sequence. *)
@ -168,6 +197,10 @@ val sort : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t
val sort_uniq : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t val sort_uniq : ?cmp:('a -> 'a -> int) -> 'a t -> 'a t
(** Sort the sequence and remove duplicates. Eager, same as [sort] *) (** Sort the sequence and remove duplicates. Eager, same as [sort] *)
val sorted : ?cmp:('a -> 'a -> int) -> 'a t -> bool
(** Checks whether the sequence is sorted. Eager, same as {!sort}.
@since NEXT_RELEASE *)
val group_succ_by : ?eq:('a -> 'a -> bool) -> 'a t -> 'a list t val group_succ_by : ?eq:('a -> 'a -> bool) -> 'a t -> 'a list t
(** Group equal consecutive elements. (** Group equal consecutive elements.
Formerly synonym to [group]. Formerly synonym to [group].
@ -189,6 +222,11 @@ val product : 'a t -> 'b t -> ('a * 'b) t
as required (several times), possibly by calling {!persistent} on it as required (several times), possibly by calling {!persistent} on it
beforehand. *) beforehand. *)
val diagonal : 'a list -> ('a * 'a) t
(** All pairs of distinct positions of the list. [diagonal l] will
return the list of [List.nth i l, List.nth j l] if [i < j].
@since NEXT_RELEASE *)
val product2 : 'a t -> 'b t -> ('a, 'b) t2 val product2 : 'a t -> 'b t -> ('a, 'b) t2
(** Binary version of {!product}. Same requirements. *) (** Binary version of {!product}. Same requirements. *)
@ -382,6 +420,10 @@ val int_range_by : step:int -> start:int -> stop:int -> int t
@since NEXT_RELEASE @since NEXT_RELEASE
@raise Invalid_argument if [step=0] *) @raise Invalid_argument if [step=0] *)
val bools : bool t
(** Iterates on [true] and [false]
@since NEXT_RELEASE *)
val of_set : (module Set.S with type elt = 'a and type t = 'b) -> 'b -> 'a t val of_set : (module Set.S with type elt = 'a and type t = 'b) -> 'b -> 'a t
(** Convert the given set to a sequence. The set module must be provided. *) (** Convert the given set to a sequence. The set module must be provided. *)