diff --git a/AUTHORS.adoc b/AUTHORS.adoc index 56dba742..93b85e2b 100644 --- a/AUTHORS.adoc +++ b/AUTHORS.adoc @@ -27,3 +27,4 @@ - Orbifx (Stavros Polymenis) - Rand (@rand00) - Dave Aitken (@actionshrimp) +- Etienne Millon (@emillon) diff --git a/src/core/CCFun.ml b/src/core/CCFun.ml index 60bd7c73..e9e49878 100644 --- a/src/core/CCFun.ml +++ b/src/core/CCFun.ml @@ -66,6 +66,26 @@ let finally2 ~h f x y = ignore (h ()); raise e +let rec iterate n f x = + if n < 0 then + invalid_arg "CCFun.iterate" + else if n = 0 then + x + else + iterate (n - 1) f (f x) + +(*$= iterate & ~printer:Q.Print.int + 10 (iterate 0 succ 10) + 11 (iterate 1 succ 10) + 12 (iterate 2 succ 10) + 15 (iterate 5 succ 10) +*) +(*$R + assert_raises + (Invalid_argument "CCFun.iterate") + (fun () -> iterate (-1) succ 10) +*) + module Monad(X : sig type t end) = struct type 'a t = X.t -> 'a let return x _ = x diff --git a/src/core/CCFun.mli b/src/core/CCFun.mli index ca630f7c..55d82c1e 100644 --- a/src/core/CCFun.mli +++ b/src/core/CCFun.mli @@ -76,6 +76,11 @@ val opaque_identity : 'a -> 'a in OCaml >= 4.03). @since 0.18 *) +val iterate : int -> ('a -> 'a) -> 'a -> 'a +(** [iterate n f] is [f] iterated [n] times. That is to say, [iterate 0 f x] is + [x], [iterate 1 f x] is [f x], [iterate 2 f x] is [f (f x)], etc. + @since NEXT_RELEASE *) + (** {2 Monad} Functions with a fixed domain are monads in their codomain. *)