是否可以创建一个在 OCaml 中从左到右计算参数的运算符

But*_*ium 5 evaluation ocaml operators lazy-sequences ppx

当您定义一个运算符时,例如

let (++) a b = a :: b 
Run Code Online (Sandbox Code Playgroud)

当你这样做时

let v = foo a ++ bar b 
Run Code Online (Sandbox Code Playgroud)

bar 在 foo 之前评估。解决方法是使用 let 表达式,即

let e1 = foo a in let e2 = bar b in e1 ++ e2
Run Code Online (Sandbox Code Playgroud)

然而,有时定义一个运算符会很方便,例如它总是从左到右进行计算。有没有办法在 OCaml 中或使用 ppx 或 with 来做到这一点lazy

oct*_*ron 4

函数参数的计算顺序是语言语义的一部分(目前 OCaml 中未指定),您无法更改它。

通常,每当函数参数的求值顺序开始重要时,就表明存在太多松散的全局可变状态,并且您希望加强对可变状态的控制。

例如,如果您需要在全局状态上强制执行严格的突变顺序,常见的解决方案是使用状态单子,或者更急切的变体,例如

type context (* all of your previous global state should fit here *)
type 'a data_and_context = context * 'a
type 'a m = context -> 'a data_and_context
val (>>=): 'a m -> ('a -> 'b m) -> 'b m 
Run Code Online (Sandbox Code Playgroud)

这本质上使您能够定义自己如何评估状态

foo x >>= bar x
Run Code Online (Sandbox Code Playgroud)

  • @Butanium 假设您需要“打印”一个字符串(这里全局可变状态是“输出”)。您可以定义“type context = string”和“let (>>=) (output, x) f = let (output', result) = fx in (output ^ output', result)”。在这里,“打印”的函数应该返回打印的字符串。粗略地说,这就是 Haskell 中的 IO monad。这样做不需要突变,也不需要全局变量,因此它使你的函数变得纯净(或者至少比以前*更*纯净),因此评估的顺序并不重要(正如它应该的那样,这就是为什么OCaml 中未指定) (2认同)