I have been working on a toy example that better demonstrates the problem with OCaml’s current effect handling system:
open Effect
open Effect.Deep
open Eio
type _ Effect.t += Log : string -> unit t
(* The following function is not aware of any fibers. *)
let logging_with_prefix prefix f =
try_with f ()
{
effc =
(fun (type a) (eff : a t) ->
match eff with
| Log message ->
Some
(fun (k : (a, _) continuation) ->
print_string prefix;
print_endline message;
continue k ())
| _ -> None);
}
(* The following function is not aware of any fibers. *)
let logging = logging_with_prefix "LOG: "
(* The following function is not aware of any fibers. *)
let logging_important = logging_with_prefix "LOG IMPORTANT: "
(* The following function is generic and not aware of any effects. *)
let do_twice_parallel f = Fiber.both f f
(* The following function is performing but not handling any effects. *)
let double_hello () = do_twice_parallel (fun () -> perform (Log "Hello World!"))
let foo () =
Fiber.both
(fun () ->
(* This should run concurrently with fibers spawned outside [foo]. *)
for i = 1 to 5 do
perform (Log ("tick " ^ string_of_int i));
Fiber.yield ()
done)
(fun () ->
(* We only want this to be logged specially. *)
logging_important double_hello)
let () =
logging (fun () ->
Eio_main.run (fun _env ->
Fiber.both foo (fun () ->
for i = 1 to 5 do
perform (Log ("tock " ^ string_of_int i));
Fiber.yield ()
done)))
instead, without changing the function double_hello and while further keeping do_twice_parallel generic (edit: and without tapping into Eio’s private effects)? I don’t think that’s possible, is it?