Do Notation in OCaml



OCaml是否具有与Haskell的Do Notation等价的函数?

另一种说法是,有没有一种简单的方法可以更容易地处理嵌套的一元操作。。。因为这很烦人:

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)

是的,由于OCaml 4.08,可以描述let运算符。例如:

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

这使得以接近直接风格的风格编写程序成为可能:

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

您可以描述大量的运算符,例如单元运算符(例如bindlet*maplet+(、应用运算符(例如,maplet+product(或zip(的and+(等。

否则,可以使用语法扩展,例如https://github.com/janestreet/ppx_let目前,它比let运营商提供了更多的可能性。如果你想要let操作符的例子,在序言(无耻的插件(中,我们定义了很多!

edit:正如@ivg所说,您可以使用$ ∣  & ∣  * ∣  + ∣  - ∣  / ∣  = ∣  > ∣  @ ∣  ^ ∣  |中的任何一个来定义letand运算符。

请参阅:https://ocaml.org/manual/bindingops.html

除非你特别试图混淆你的代码,否则在没有do符号的情况下编写一元代码是非常容易的,例如,如果我们从你的例子中删除过多的1括号,它就已经很可读了,

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

如果我们将使用let绑定运算符,例如,使用monads[1,2]库(也是一个无耻的插件(,那么我们可以编写更简洁的

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通过并置表示应用程序操作(函数对其参数的应用和构造函数对其自变量的应用(,例如sin x(而非sin(x)(或Ok 42(非Ok (42)(,此外,应用程序运算符比中缀运算符具有更高的优先级(绑定更紧密(,因此可以编写sin x > cos x。lambda算子fun <var> -> <expr>与一元算子(例如(很好地连锁

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

与相同

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

或者,更多时候它被写为

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

作为对lambda(抽象(运算符的let遗留问题的致敬,参见

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

OCaml的最新版本甚至允许你双关右手边,例如

let* x in
let* y in
x + y

甚至

let* x and* y in
x + y

最新更新