wip: add to_seq and of_seq, the former using effects.

We need effects to invert control flow and transform the straightforward
iteration (say, on a tree), into a resumable Seq.t.
This commit is contained in:
Simon Cruanes 2022-02-14 22:00:49 -05:00
parent b4ceba4cb0
commit 06f49690e5
No known key found for this signature in database
GPG key ID: 4AC01D0849AA62B6
2 changed files with 69 additions and 0 deletions

View file

@ -1007,6 +1007,67 @@ let[@inline] of_list l k = List.iter k l
let on_list f l =
to_list (f (of_list l))
let of_seq seq k =
Seq.iter k seq
let to_seq (type a) (self:a t) : a Seq.t =
let stop = ref false in
let cur = ref None in
let module M = struct
type _ EffectHandlers.eff +=
| Yield : a -> unit EffectHandlers.eff
end in
let iter () : unit =
self (fun x -> EffectHandlers.perform (M.Yield x));
stop := true;
cur := None;
in
let k: _ EffectHandlers.Shallow.continuation ref
= ref (EffectHandlers.Shallow.fiber iter) in
let effc
: type c. c EffectHandlers.eff -> ((c,_) EffectHandlers.Shallow.continuation -> _) option
= function
| M.Yield x ->
cur := Some x;
Some (fun k' -> k := k')
| _ -> None
in
let handler = {
EffectHandlers.Shallow.retc=ignore; exnc=ignore; effc;
} in
let rec next () =
if !stop then Seq.Nil
else (
EffectHandlers.Shallow.continue_with !k () handler;
match !cur with
| None -> Seq.Nil
| Some x -> Seq.Cons (x, next)
)
in
next
(*$R
let seq = ref @@ to_seq (1 -- 5) in
let next () = match (!seq) () with
| Seq.Nil -> None
| Seq.Cons (x,tl) -> seq := tl; Some x
in
assert_equal ~printer:(Q.Print.(option int)) (Some 1) (next ());
assert_equal ~printer:(Q.Print.(option int)) (Some 2) (next ());
assert_equal ~printer:(Q.Print.(option int)) (Some 3) (next ());
assert_equal ~printer:(Q.Print.(option int)) (Some 4) (next ());
assert_equal ~printer:(Q.Print.(option int)) (Some 5) (next ());
assert_equal ~printer:(Q.Print.(option int)) None (next ());
*)
let pair_with_idx seq k =
let r = ref 0 in
seq (fun x -> let n = !r in incr r; k (n,x))

View file

@ -542,6 +542,14 @@ val on_list : ('a t -> 'b t) -> 'a list -> 'b list
@since 0.5.2
*)
val of_seq : 'a Seq.t -> 'a t
(** Iterate on the sequence.
@since NEXT_RELEASE *)
val to_seq : 'a t -> 'a Seq.t
(** Sequence from the iterator (using effects).
@since NEXT_RELEASE *)
val pair_with_idx : 'a t -> (int * 'a) t
(** Similar to {!zip_i} but returns a normal iterator of tuples
@since 0.11 *)