reasonml / reason

Simple, fast & type safe code that leverages the JavaScript & OCaml ecosystems
http://reasonml.github.io
MIT License
10.14k stars 430 forks source link

Syntax proposal: F# like syntax for monads "let!" #1353

Closed modlfo closed 3 months ago

modlfo commented 7 years ago

One thing that I miss from F# when working in OCaml is the possibility of writing monadic bindings (that are readable) without the need of a ppx preprocessor like ppx_let.

I think that the F# syntax could fit nicely with the current syntax of Reason. Here are more details https://docs.microsoft.com/en-gb/dotnet/fsharp/language-reference/computation-expressions

For example:

(* F# code *)
let foo () =
   async {
      let! x = do_something ()
      do! y = do_something_else ()
      return x + y
   }

which already looks pretty much like Reason:

(* Reason equivalent *)
let foo () =>
   async {
      let! x = do_something ();
      do! y = do_something_else ();
      return x + y;
   }

If you are not familiar with the F# syntax, the let! is replaced by the bind function defined in the module async.

bassjacob commented 7 years ago

Would this be similar to https://github.com/janestreet/ppx_let ? If so, you can use this ppx with your projects already.

If the goal is the async/awaiy equivalent, there's some really good work to make https://github.com/ocsigen/lwt work well with reason and bucklescript, which should help some.

modlfo commented 7 years ago

I'll elaborate further.

In principle my proposal is to integrate something similar to ppx_let into Reason, but with what I think is a good syntax; the F# syntax. The reason why I think this would be better are:

In addition the F# syntax described here consider other useful cases like try, for, while which are also used in ppx_lwt. It worths taking a look at it.

Here's another example comparing it to OCaml:

(* OCaml code with ppx_let *)
let foo () =
   let open MyMonad in
   let%bind x = bar () in
   let%bind y = bob x in
   return y

Same code with Reason (F# like syntax)

(* Reason code with the proposed syntax *)
let foo ()  =>
   MyMonad {
      let! x = bar () in
      let! y = bob x in
      return y
}
hcarty commented 7 years ago

What does Reason use for its equivalent(s) to open!, method! and other override syntax? Part of the reason that specific let! syntax wasn't added to OCaml was because of the very different meanings between the ! suffix in those uses.

modlfo commented 7 years ago

@hcarty If I understood correctly, what you mean is that ! can be a suffix of open and method. I think that F# implements only: let!, do!,yield!, use!, and return!. And by looking at the tokenizer code here, the tokenizer tries to match the full let! string. Therefore let ! (with a space) is not the same as let! (with no space). The ! in let! cannot be overloaded to behave differently.

hcarty commented 7 years ago

@modlfo I just mean that the ! suffix on a keyword in OCaml has a meaning already which has nothing to do with monads. I think the same meaning is maintained in Reason. That should be taken into account when considering a let! syntax to avoid inconsistencies. Either a different suffix should be chosen for let in the monad case or the suffix used for overriding in other keywords should be changed.

modlfo commented 7 years ago

@hcarty Thanks for the clarification. I was not aware that open! or method! existed since I never seen them used before.

andreypopp commented 6 years ago

I proposed a generic monadic syntax based on ppx_let semantics in https://github.com/facebook/reason/issues/1321#issuecomment-348714613

anmonteiro commented 3 months ago

Binding ops solve this problem today