diff --git a/src/core/CCSeq.ml b/src/core/CCSeq.ml index b0747f4e..302c51be 100644 --- a/src/core/CCSeq.ml +++ b/src/core/CCSeq.ml @@ -21,6 +21,13 @@ let nil () = Nil let cons a b () = Cons (a, b) let empty = nil let singleton x () = Cons (x, nil) + +let init n f = + let rec aux i () = + if i >= n then Nil else Cons (f i, aux (i+1)) + in + aux 0 + let rec _forever x () = Cons (x, _forever x) let rec _repeat n x () = @@ -34,6 +41,8 @@ let repeat ?n x = | None -> _forever x | Some n -> _repeat n x +let rec forever f () = Cons (f (), forever f) + let is_empty l = match l () with | Nil -> true @@ -59,6 +68,11 @@ let tail l = | Nil -> None | Cons (_, l) -> Some l +let uncons l = + match l () with + | Nil -> None + | Cons (h, t) -> Some (h, t) + let rec equal eq l1 l2 = match l1 (), l2 () with | Nil, Nil -> true @@ -84,6 +98,16 @@ let rec fold f acc res = let fold_left = fold +let foldi f acc res = + let rec aux acc i res = + match res () with + | Nil -> acc + | Cons (s, cont) -> aux (f acc i s) (i+1) cont + in + aux acc 0 res + +let fold_lefti = foldi + let rec iter f l = match l () with | Nil -> () @@ -170,6 +194,8 @@ let rec append l1 l2 () = let rec cycle l () = append l (cycle l) () +let rec iterate f a () = Cons (a, iterate f (f a)) + let rec unfold f acc () = match f acc with | None -> Nil @@ -185,6 +211,26 @@ let rec exists p l = | Nil -> false | Cons (x, tl) -> p x || exists p tl +let rec find p l = + match l () with + | Nil -> None + | Cons (x, tl) -> + if p x then Some x else find p tl + +let rec find_map f l = + match l () with + | Nil -> None + | Cons (x, tl) -> + match f x with + | None -> find_map f tl + | e -> e + +let rec scan f acc res () = Cons (acc, fun () -> + match res () with + | Nil -> Nil + | Cons (s, cont) -> scan f (f acc s) cont ()) + + let rec flat_map f l () = match l () with | Nil -> Nil @@ -195,6 +241,8 @@ and _flat_map_app f l l' () = | Nil -> flat_map f l' () | Cons (x, tl) -> Cons (x, _flat_map_app f tl l') +let concat = flat_map + let product_with f l1 l2 = let rec _next_left h1 tl1 h2 tl2 () = match tl1 () with @@ -218,6 +266,8 @@ let product_with f l1 l2 = in _next_left [] l1 [] l2 +let map_product = product_with + let product l1 l2 = product_with (fun x y -> x, y) l1 l2 let rec group eq l () = @@ -248,6 +298,8 @@ let rec filter_map f l () = let flatten l = flat_map (fun x -> x) l +let concat = flatten + let range i j = let rec aux i j () = if i = j then @@ -274,6 +326,8 @@ let rec fold2 f acc l1 l2 = | Nil, _ | _, Nil -> acc | Cons (x1, l1'), Cons (x2, l2') -> fold2 f (f acc x1 x2) l1' l2' +let fold_left2 = fold2 + let rec map2 f l1 l2 () = match l1 (), l2 () with | Nil, _ | _, Nil -> Nil @@ -306,6 +360,8 @@ let rec merge cmp l1 l2 () = else Cons (x2, merge cmp l1 l2') +let sorted_merge = merge + let rec zip a b () = match a (), b () with | Nil, _ | _, Nil -> Nil @@ -323,6 +379,8 @@ let unzip l = in first l, second l +let split = unzip + let zip_i seq = let rec loop i seq () = match seq () with diff --git a/src/core/CCSeq.mli b/src/core/CCSeq.mli index bb6f0675..2de29176 100644 --- a/src/core/CCSeq.mli +++ b/src/core/CCSeq.mli @@ -29,19 +29,34 @@ val empty : 'a t val cons : 'a -> 'a t -> 'a t val singleton : 'a -> 'a t +val init : int -> (int -> 'a) -> 'a t +(** [init n f] corresponds to the sequence [f 0; f 1; ...; f (n-1)]. + @raise Invalid_argument if n is negative. + @since NEXT_RELEASE *) + val repeat : ?n:int -> 'a -> 'a t (** [repeat ~n x] repeats [x] [n] times then stops. If [n] is omitted, then [x] is repeated forever. *) +val forever : (unit -> 'a) -> 'a t +(** [forever f] corresponds to the infinit sequence containing all the [f ()]. + @since NEXT_RELEASE *) + val cycle : 'a t -> 'a t (** Cycle through the iterator infinitely. The iterator shouldn't be empty. *) +val iterate : ('a -> 'a) -> 'a -> 'a t +(** [iterate f a] corresponds to the infinit sequence containing [a], [f a], [f (f a)], + ...] + @since NEXT_RELEASE *) + val unfold : ('b -> ('a * 'b) option) -> 'b -> 'a t (** [unfold f acc] calls [f acc] and: - if [f acc = Some (x, acc')], yield [x], continue with [unfold f acc']. - if [f acc = None], stops. *) val is_empty : 'a t -> bool +(** [is_empty xs] checks in the sequence [xs] is empty *) val head : 'a t -> 'a option (** Head of the list. *) @@ -57,6 +72,10 @@ val tail_exn : 'a t -> 'a t (** Unsafe version of {!tail}. @raise Not_found if the list is empty. *) +val uncons : 'a t -> ('a * 'a t) option +(** [uncons xs] return [None] if [xs] is empty other + @since NEXT_RELEASE *) + val equal : 'a equal -> 'a t equal (** Equality step by step. Eager. *) @@ -69,6 +88,16 @@ val fold : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a (** Alias for {!fold} *) +val foldi : ('a -> int -> 'b -> 'a) -> 'a -> 'b t -> 'a +(** [fold_lefti f init xs] applies [f acc i x] where [acc] is the result of the previous + computation or [init] for the first one, [i] is the index in the sequence (starts at + 0) and [x] is the element of the sequence. + @since NEXT_RELEASE *) + +val fold_lefti : ('a -> int -> 'b -> 'a) -> 'a -> 'b t -> 'a +(** Alias of {!foldi}. + @since NEXT_RELEASE *) + val iter : ('a -> unit) -> 'a t -> unit val iteri : (int -> 'a -> unit) -> 'a t -> unit @@ -96,6 +125,10 @@ val product_with : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t (** Fair product of two (possibly infinite) lists into a new list. Lazy. The first parameter is used to combine each pair of elements. *) +val map_product : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t +(** Alias of {!product_with}. + @since NEXT_RELEASE *) + val product : 'a t -> 'b t -> ('a * 'b) t (** Specialization of {!product_with} producing tuples. *) @@ -123,9 +156,33 @@ val exists : ('a -> bool) -> 'a t -> bool sequence until it finds an element satisfying the predicate. @since 3.3 *) +val find : ('a -> bool) -> 'a t -> 'a option +(** [find p [a1; ...; an]] return [Some ai] for the first [ai] satisfying the predicate + [p] and return [None] otherwise. + @since NEXT_RELEASE *) + +val find_map : ('a -> 'b option) -> 'a t -> 'b option +(** [find f [a1; ...; an]] return [Some (f ai)] for the first [ai] such that + [f ai = Some _] and return [None] otherwise. + @since NEXT_RELEASE *) + +val scan : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a t +(** [scan f init xs] is the sequence containing the intermediate result of + [fold f init xs]. + @since NEXT_RELEASE *) + val flat_map : ('a -> 'b t) -> 'a t -> 'b t +val concat_map : ('a -> 'b t) -> 'a t -> 'b t +(** Aliass of {!flat_map} + @since NEXT_RELEASE *) + val filter_map : ('a -> 'b option) -> 'a t -> 'b t + val flatten : 'a t t -> 'a t +val concat : 'a t t -> 'a t +(** Alias of {!flatten}. + @since NEXT_RELEASE *) + val range : int -> int -> int t val ( -- ) : int -> int -> int t @@ -140,6 +197,10 @@ val ( --^ ) : int -> int -> int t val fold2 : ('acc -> 'a -> 'b -> 'acc) -> 'acc -> 'a t -> 'b t -> 'acc (** Fold on two collections at once. Stop at soon as one of them ends. *) +val fold_left2 : ('acc -> 'a -> 'b -> 'acc) -> 'acc -> 'a t -> 'b t -> 'acc +(** Alias for {!fold2}. + @since NEXT_RELEASE *) + val map2 : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t (** Map on two collections at once. Stop as soon as one of the arguments is exhausted. *) @@ -153,12 +214,20 @@ val exists2 : ('a -> 'b -> bool) -> 'a t -> 'b t -> bool val merge : 'a ord -> 'a t -> 'a t -> 'a t (** Merge two sorted iterators into a sorted iterator. *) +val sorted_merge : 'a ord -> 'a t -> 'a t -> 'a t +(** Alias of {!merge}. + @since NEXT_RELEASE *) + val zip : 'a t -> 'b t -> ('a * 'b) t (** Combine elements pairwise. Stop as soon as one of the lists stops. *) val unzip : ('a * 'b) t -> 'a t * 'b t (** Split each tuple in the list. *) +val split : ('a * 'b) t -> 'a t * 'b t +(** Alias of {!unzip}. + @since NEXT_RELEASE *) + val zip_i : 'a t -> (int * 'a) t (** [zip_i seq] zips the index of each element with the element itself. @since 3.8