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