Greg
Greg

Reputation: 3150

Do Notation in OCaml

Does OCaml have an equivalent to Haskell's Do Notation?

Another way to put it - is there an easy way to handle nesting monadic operations more easily... cause this is annoying:

open Batteries
open BatResult.Infix

let () =
  let out = 
    (Ok("one")) >>=
      (fun a -> 
        let b = Ok("two") in
        b >>= (fun c -> 
          print_endline(a);
          print_endline(c);
          Ok(c)
          )) in
  ignore(out)
  

Upvotes: 10

Views: 1829

Answers (2)

ivg
ivg

Reputation: 35280

Unless you specifically try to obfuscate your code, writing monadic code without do-notation is pretty easy, e.g., if we will remove excessive1 parentheses from your example it will be already pretty readable,

let v0 =
  Ok "one" >>= fun a ->
  Ok "two" >>= fun c ->
  print_endline a;
  print_endline c;
  Ok c

And if we will use let-binding operators, e.g., using the monads [1,2] library (also a shameless plug), then we can write it even more concise,

open Monads.Std

open Monad.Result.Error.Syntax
open Monad.Result.Error.Let

let v1 =
  let+ a = Ok "one" and+ b = Ok "two" in
  print_endline a;
  print_endline b;
  b

1) OCaml denotes the application operation (both an application of a function to its argument and an application a constructor to its argument) by juxtaposition, e.g., sin x (not sin(x)), or Ok 42 (not Ok (42)), moreover the application operator has higher precedence (binds tighter) than infix operators, so you can write sin x > cos x. The lambda operator, fun <var> -> <expr> chains nicely with monadic operators, e.g.,

x >>= (fun x -> y >>= (fun y -> x + y))

is the same as

x >>= fun x -> y >>= fun y -> x + y

or, more often it is written as

x >>= fun x -> 
y >>= fun y ->
x + y

as a tribute to the let-legacy of the lambda (abstraction) operator, cf.,

let* x = x in
let* y = y in
x + y

and latest versions of OCaml even allow you to pun the right-hand side, e.g.,

let* x in
let* y in
x + y

or even

let* x and* y in
x + y

Upvotes: 8

X. Van de Woestyne
X. Van de Woestyne

Reputation: 637

Yes, since OCaml 4.08, it is possible to describe let operators. For example:

let (let*) x f = BatResult.bind x f 
let (let+) x f = BatResult.map f x

This makes it possible to write programs in a style close to the direct style:

let out = 
  let* a = Ok "one" in 
  let* b = Ok "two" in 
  let () = print_endline a in 
  let () = print_endline b in 
  Ok b

You can describe a large number of operators, for monads (e.g. let* for bind and let+ for map), for applicative (e.g. let+ for map and and+ for product (or zip)) etc.

Otherwise it is possible to use syntax extensions, for example https://github.com/janestreet/ppx_let which, for the moment, offers even more possibilities than the let operators. If you ever want examples of let operators, in Preface (shameless plug), we define plenty of them!

edit: As @ivg says, you can use any of $ ∣  & ∣  * ∣  + ∣  - ∣  / ∣  = ∣  > ∣  @ ∣  ^ ∣  | for defining your let or and operator.

see: https://ocaml.org/manual/bindingops.html

Upvotes: 11

Related Questions