mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-07 11:45:31 -05:00
add CCLazy_list in containers.iter (with a few functions)
This commit is contained in:
parent
c14191f1bd
commit
a3d763bfd9
4 changed files with 171 additions and 2 deletions
2
_oasis
2
_oasis
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -116,7 +116,10 @@ CCSexpM
|
|||
|
||||
Iterators:
|
||||
|
||||
{!modules: CCKList CCKTree}
|
||||
{!modules:
|
||||
CCKList
|
||||
CCKTree
|
||||
CCLazy_list}
|
||||
|
||||
{4 String}
|
||||
|
||||
|
|
|
|||
109
src/iter/CCLazy_list.ml
Normal file
109
src/iter/CCLazy_list.ml
Normal 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
57
src/iter/CCLazy_list.mli
Normal 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
|
||||
Loading…
Add table
Reference in a new issue