add CCLazy_list in containers.iter (with a few functions)

This commit is contained in:
Simon Cruanes 2016-04-21 15:20:18 +02:00
parent c14191f1bd
commit a3d763bfd9
4 changed files with 171 additions and 2 deletions

2
_oasis
View file

@ -88,7 +88,7 @@ Library "containers_data"
Library "containers_iter"
Path: src/iter
Modules: CCKTree, CCKList
Modules: CCKTree, CCKList, CCLazy_list
FindlibParent: containers
FindlibName: iter

View file

@ -116,7 +116,10 @@ CCSexpM
Iterators:
{!modules: CCKList CCKTree}
{!modules:
CCKList
CCKTree
CCLazy_list}
{4 String}

109
src/iter/CCLazy_list.ml Normal file
View file

@ -0,0 +1,109 @@
(* This file is free software, part of containers. See file "license" for more details. *)
(** {1 Lazy List} *)
type +'a t = 'a node lazy_t
and +'a node =
| Nil
| Cons of 'a * 'a t
let empty = Lazy.from_val Nil
let return x = Lazy.from_val (Cons (x, empty))
let is_empty = function
| lazy Nil -> true
| lazy (Cons _) -> false
let cons x tl = Lazy.from_val (Cons (x,tl))
let head = function
| lazy Nil -> None
| lazy (Cons (x, tl)) -> Some (x,tl)
let length l =
let rec aux acc l = match l with
| lazy Nil -> acc
| lazy (Cons (_, tl)) -> aux (acc+1) tl
in
aux 0 l
(*$Q
Q.(list int) (fun l -> length (of_list l) = List.length l)
*)
let rec map ~f l =
lazy (
match l with
| lazy Nil -> Nil
| lazy (Cons (x,tl)) -> Cons (f x, map ~f tl)
)
let rec append a b =
lazy (
match a with
| lazy Nil -> Lazy.force b
| lazy (Cons (x,tl)) -> Cons (x, append tl b)
)
(*$Q
Q.(pair (list int) (list int)) (fun (l1,l2) ->\
length (append (of_list l1) (of_list l2)) = List.length l1 + List.length l2)
*)
let rec flat_map ~f l =
lazy (
match l with
| lazy Nil -> Nil
| lazy (Cons (x,tl)) ->
let res = append (f x) (flat_map ~f tl) in
Lazy.force res
)
module Infix = struct
let (>|=) x f = map ~f x
let (>>=) x f = flat_map ~f x
end
include Infix
type 'a gen = unit -> 'a option
let rec of_gen g =
lazy (
match g() with
| None -> Nil
| Some x -> Cons (x, of_gen g)
)
(*$Q
Q.(list int) (fun l -> l = (Gen.of_list l |> of_gen |> to_list))
*)
let rec of_list = function
| [] -> empty
| x :: tl -> cons x (of_list tl)
let to_list_rev l =
let rec aux acc = function
| lazy Nil -> acc
| lazy (Cons (x,tl)) -> aux (x::acc) tl
in
aux [] l
let to_list l = to_list_rev l |> List.rev
(*$Q
Q.(list int) (fun l -> l = to_list (of_list l))
*)
let to_gen l =
let l = ref l in
fun () -> match !l with
| lazy Nil -> None
| lazy (Cons (x,tl)) -> l := tl; Some x
(*$Q
Q.(list int) (fun l -> l = (of_list l |> to_gen |> Gen.to_list))
*)

57
src/iter/CCLazy_list.mli Normal file
View file

@ -0,0 +1,57 @@
(* This file is free software, part of containers. See file "license" for more details. *)
(** {1 Lazy List}
@since NEXT_RELEASE *)
type +'a t = 'a node lazy_t
and +'a node =
| Nil
| Cons of 'a * 'a t
val empty : 'a t
(** Empty list *)
val return : 'a -> 'a t
(** Return a computed value *)
val is_empty : _ t -> bool
(** Evaluates the head *)
val length : _ t -> int
(** [length l] returns the number of elements in [l], eagerly (linear time).
Caution, will not terminate if [l] is infinite *)
val cons : 'a -> 'a t -> 'a t
val head : 'a t -> ('a * 'a t) option
(** Evaluate head, return it, or [None] if the list is empty *)
val map : f:('a -> 'b) -> 'a t -> 'b t
(** Lazy map *)
val append : 'a t -> 'a t -> 'a t
(** Lazy concatenation *)
val flat_map : f:('a -> 'b t) -> 'a t -> 'b t
(** Monadic flatten + map *)
module Infix : sig
val (>|=) : 'a t -> ('a -> 'b) -> 'b t
val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
end
include module type of Infix
type 'a gen = unit -> 'a option
val of_gen : 'a gen -> 'a t
val of_list : 'a list -> 'a t
val to_list : 'a t -> 'a list
val to_list_rev : 'a t -> 'a list
val to_gen : 'a t -> 'a gen