-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
The behaviour when we catch an effect which is not a part of Miou #10
Comments
Since #11, we are able to compose Miou with something else which emits effects. The idea is to keep the rule: an effect suspends a task. type _ Effect.t += Foo : unit Effect.t
let prgm () =
let prm = Miou.call @@ fun () -> Effect.perform Foo in
Miou.await_exn prm
let handler_foo fn v =
let open Effect.Deep in
let retc = Fun.id in
let exnc = raise in
let effc : type c. c Effect.t -> ((c, 'a) continuation -> 'b) option =
function
| Foo -> Some (fun k -> continue k ())
| _ -> None
in
match_with fn v { retc; exnc; effc }
let () =
Miou.run ~handler:{ Miou.handler= handler_foo } @@ fun () ->
let prm = Miou.call @@ fun () -> Effect.perform Foo in
Miou.await_exn prm
let () =
Miou.run ~handler:{ Miou.handler= handler_foo } @@ fun () ->
let prm = Miou.call_cc @@ fun () -> Effect.perform Foo in
Miou.await_exn prm
type _ Effect.t += Bar : unit Effect.t
let handler_bar fn v =
let open Effect.Deep in
let retc = Fun.id in
let exnc = raise in
let effc : type c. c Effect.t -> ((c, 'a) continuation -> 'b) option =
function
| Bar -> Some (fun k -> continue k ())
| _ -> None
in
match_with fn v { retc; exnc; effc }
let ( <.> ) { Miou.handler= foo } { Miou.handler= bar } =
{ Miou.handler= (fun fn v -> (foo (bar fn)) v) }
let () =
let foo = { Miou.handler= handler_foo } in
let bar = { Miou.handler= handler_bar } in
Miou.run ~handler:(foo <.> bar) @@ fun () ->
let prm0 = Miou.call @@ fun () -> Effect.perform Foo in
let prm1 = Miou.call @@ fun () -> Effect.perform Bar in
Miou.await_exn prm0; Miou.await_exn prm1 I let this issue open due to the experimental stage of this design. Feel free to debate about the best to provide on the API level. |
I would recommend not handling unknown effects and allowing the runtime to raise the This allows library and application code to handle the Note that this comment does not concern the use of some sort of extension mechanism to e.g. add user defined handlers to (the fibers started by) a scheduler. What I just mean is that OCaml already has a notion of an |
So currently, if we don't handle an effect (the user has neither specified a Miou # type _ Effect.t += Foo : unit Effect.t
# let () = Miou.run @@ fun () -> Effect.perform Foo;;
Exception: Stdlib.Effect.Unhandled(Foo) What happens is that Miou catches the effect and then re-performs the effect. We do this to respect the rule: an effect supends the task. What do you think? |
Does this mean that an effect that is unkown to Miou basically has the same effect as Basically, using try Effect.perform My_effect
with Effect.Unhandled My_effect ->
default_implementation_of_my_effect () to allow an effect to be optionally handled with a default fallback behavior. This is reasonably performant as setting an exception handler does not allocate and only requires a few instructions. If a scheduler would then go out of its way to handle the effect by suspending the fiber and then later reperforming the effect, then it would potentially make the above pattern unusably slow. It would also mean that the effect would not be synchronous/atomic (between fibers running on the scheduler), which is another limitation. So, my recommendation is that any unknown effects should not be handled. Just return |
Yes, that the initial idea. Your pattern is indeed valid and, in the choice to catch up and relaunch, this code doesn't work as intended: # type _ Effect.t += Foo : unit Effect.t
# let () = Miou.run @@ fun () ->
try Effect.perform Foo
with Effect.Unhandled Foo -> () ;;
Exception: Stdlib.Effect.Unhandled(Foo) However, if you want to manage this kind of pattern, you can't just ensure that an effect is like Yield. I don't have any strong opinions on this and we could just declare that the production of effects specified by Miou are the only ones that suspend a task. I need to think more about that and find the right cursor 👍 - but if you have some concerns, please share! |
I would agree with polytopic here. If Effects are to become a more widely used language feature outside of schedulers, I believe Miou should only handle it's own - doing otherwise is just going to put Miou at odds with any novel uses for effects that happen to need to catch |
Currently, if an application emits an effect which is not defined by Miou, we raise an exception. It will be nice to think about the right behavior to have in such situation.
This has been mentioned at https://discuss.ocaml.org/t/ann-miou-a-simple-scheduler-for-ocaml-5/12963/9
The text was updated successfully, but these errors were encountered: