From 13028c3d178338594014214f5df645afef163f33 Mon Sep 17 00:00:00 2001 From: Bertrand Bonnefoy-Claudet Date: Mon, 29 Mar 2021 22:40:08 +0200 Subject: [PATCH] CCSeq: Add `for_all` and `exists` The functions are implemented the same way as in `oseq` and their documentation is inspired from their counterparts in `Stdlib.List`. --- src/core/CCSeq.ml | 34 ++++++++++++++++++++++++++++++++++ src/core/CCSeq.mli | 14 ++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/src/core/CCSeq.ml b/src/core/CCSeq.ml index 1b3aacd9..7f910857 100644 --- a/src/core/CCSeq.ml +++ b/src/core/CCSeq.ml @@ -169,6 +169,40 @@ let rec unfold f acc () = match f acc with unfold f 0 |> to_list = [0;1;2;3;4;5;6;7;8;9] *) +let rec for_all p l = + match l () with + | Nil -> true + | Cons (x, tl) -> p x && for_all p tl + +(*$T + for_all ((=) 1) (of_list []) = true + for_all ((=) 1) (of_list [0]) = false + for_all ((=) 1) (of_list [1]) = true + for_all ((=) 1) (of_list [1; 0]) = false + for_all ((=) 1) (of_list [0; 1]) = false + for_all ((=) 1) (of_list [1; 1]) = true + + let l () = Cons (0, fun () -> failwith "no second element") in \ + try ignore (for_all ((=) 1) l); true with Failure _ -> false +*) + +let rec exists p l = + match l () with + | Nil -> false + | Cons (x, tl) -> p x || exists p tl + +(*$T + exists ((=) 1) (of_list []) = false + exists ((=) 1) (of_list [0]) = false + exists ((=) 1) (of_list [1]) = true + exists ((=) 1) (of_list [1; 0]) = true + exists ((=) 1) (of_list [0; 1]) = true + exists ((=) 1) (of_list [0; 0]) = false + + let l () = Cons (1, fun () -> failwith "no second element") in \ + try ignore (exists ((=) 1) l); true with Failure _ -> false +*) + let rec flat_map f l () = match l () with | Nil -> Nil | Cons (x, l') -> diff --git a/src/core/CCSeq.mli b/src/core/CCSeq.mli index c2ea70b8..aeefa30b 100644 --- a/src/core/CCSeq.mli +++ b/src/core/CCSeq.mli @@ -126,6 +126,20 @@ val uniq : 'a equal -> 'a t -> 'a t only the first of them is kept. @since 0.3.3 *) +val for_all : ('a -> bool) -> 'a t -> bool +(** [for_all p [a1; ...; an]] checks if all elements of the sequence satisfy the + predicate [p]. That is, it returns [(p a1) && ... && (p an)] for a + non-empty list and [true] if the sequence is empty. It consumes the + sequence until it finds an element not satisfying the predicate. + @since NEXT_RELEASE *) + +val exists : ('a -> bool) -> 'a t -> bool +(** [exists p [a1; ...; an]] checks if at least one element of the sequence + satisfies the predicate [p]. That is, it returns [(p a1) || ... || (p an)] + for a non-empty sequence and [false] if the list is empty. It consumes the + sequence until it finds an element satisfying the predicate. + @since NEXT_RELEASE *) + val flat_map : ('a -> 'b t) -> 'a t -> 'b t val filter_map : ('a -> 'b option) -> 'a t -> 'b t