Implementing simple generators with effect handlers

For what it’s worth, the OCaml manual’s chapter on effects has one example of a simple yield effect handler that accepts an iter function and returns a Seq.t. The manual calls the function invert but you could easily call it generator. It’s similar to the examples above except that the consumer can’t respond to a yield.

open Effect
open Effect.Deep

let invert (type a) ~(iter : (a -> unit) -> unit) : a Seq.t =
  let module M = struct
    type _ Effect.t += Yield : a -> unit t
  end in
  let yield v = perform (M.Yield v) in
  fun () ->
    match iter yield with
    | () -> Seq.Nil
    | effect M.Yield v, k -> Seq.Cons (v, continue k)

let range start stop yield =
  for i = start to stop do
    yield i
  done

let rec print_all seq =
  match seq () with
  | Seq.Nil -> ()
  | Seq.Cons (i, next) ->
      Format.printf "yielded %i@." i;
      print_all next

let () = print_all @@ invert ~iter:(range 0 10)

4 Likes