I’m looking for something similar to Rust’s`?`

operator on functions that return `Result<T, E>`

(in particular, it shortcircuits on first error).

I found: OCaml library : Result , which has (1) the type I need and (2) the `bind`

operator I need.

I also see `let*`

from OCaml - Language extensions .

What I can’t figure out is: how do we put this together for functions that return an `('a, 'e) result`

?

I don’t understand what I am supposed to do with this. Is there a minimal repo with a dune file + a *.ml file using monadic result ?

I think it’s just meant to give you a code snippet example, specifically this should just work for whatever `bind`

, `product`

, `map`

are:

```
let return x = Ok x
let ( let* ) x f = bind x f
let ( and* ) a b = product a b
let ( let+ ) x f = map f x
let ( and+ ) a b = product a b
```

And further down there are some examples:

```
(* Option *)
let option_map =
Option.Syntax.(
let+ x = Some 4 in
x + 1
);;
[%%expect{|
val option_map : int option = Some 5
|}];;
let option_map2 =
Option.Syntax.(
let+ x = None in
x + 1
);;
[%%expect{|
val option_map2 : int option = None
|}];;
let option_map_and =
Option.Syntax.(
let+ x = Some 5
and+ y = Some 8 in
x + y
);;
[%%expect{|
val option_map_and : int option = Some 13
|}];;
let option_map_and2 =
Option.Syntax.(
let+ x = None
and+ y = Some 8 in
x + y
);;
[%%expect{|
val option_map_and2 : int option = None
|}];;
let option_map_and3 =
Option.Syntax.(
let+ x = Some 5
and+ y = None in
x + y
);;
[%%expect{|
val option_map_and3 : int option = None
|}];;
let option_bind =
Option.Syntax.(
let* x = Some 5 in
let* y = Some 6 in
return (x + y)
);;
[%%expect{|
val option_bind : int option = Some 11
|}];;
let option_bind2 =
Option.Syntax.(
let* x = None in
let* y = Some 7 in
return (x + y)
);;
[%%expect{|
val option_bind2 : int option = None
|}];;
let option_bind3 =
Option.Syntax.(
let* x = Some 3 in
let* y = None in
return (x + y)
);;
[%%expect{|
val option_bind3 : int option = None
|}];;
let option_bind_and =
Option.Syntax.(
let* x = Some 2
and* y = Some 7 in
return (x + y)
);;
[%%expect{|
val option_bind_and : int option = Some 9
|}];;
let option_bind_and2 =
Option.Syntax.(
let* x = None
and* y = Some 9 in
return (x + y)
);;
[%%expect{|
val option_bind_and2 : int option = None
|}];;
let option_bind_and3 =
Option.Syntax.(
let* x = Some 3
and* y = None in
return (x + y)
);;
[%%expect{|
val option_bind_and3 : int option = None
|}];;
let option_bind_map =
Option.Syntax.(
let* x = Some 3 in
let+ y = Some 7 in
x + y
);;
[%%expect{|
val option_bind_map : int option = Some 10
|}];;
```

Disclaimer: see the license file in the repo of the PR.

This problem is related to the concept of a monad (which I still haven’t fully understood or studied yet)

Maybe this beginner oriented example will help you understand more: multi-playground/monads.ml at master · benjamin-thomas/multi-playground · GitHub

In short, you don’t need an early return at all.

You can apply this same concept to the result type

There’s not much you need to do. Just issue a

`let ( let* ) = Result.bind`

at the toplevel of your module. You can now use `let*`

to unpack the `Ok`

case of `result`

values:

```
let read_int : () -> (int, string) result = …
let read_and_add () : (int, string) result =
let* i = read_int () in
Ok (i + 1)
```

4 Likes