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
您可以描述大量的运算符,例如单元运算符(例如bind
的let*
和map
的let+
(、应用运算符(例如,map
的let+
和product
(或zip
(的and+
(等。
否则,可以使用语法扩展,例如https://github.com/janestreet/ppx_let目前,它比let运营商提供了更多的可能性。如果你想要let操作符的例子,在序言(无耻的插件(中,我们定义了很多!
edit:正如@ivg所说,您可以使用$ ∣ & ∣ * ∣ + ∣ - ∣ / ∣ = ∣ > ∣ @ ∣ ^ ∣ |
中的任何一个来定义let
或and
运算符。
请参阅: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