只是一个快速的问题。我想知道在标准库(或 Jane Street 的核心或电池中)中定义的 OCaml 中是否有一个中缀函数组合运算符,例如 Haskell 中的 (.) 函数,它为我们节省了很多括号,因为我们可以编写(f . g . h) x
而不是不那么吸引人f (g (h x)))
。
谢谢各位。
只是一个快速的问题。我想知道在标准库(或 Jane Street 的核心或电池中)中定义的 OCaml 中是否有一个中缀函数组合运算符,例如 Haskell 中的 (.) 函数,它为我们节省了很多括号,因为我们可以编写(f . g . h) x
而不是不那么吸引人f (g (h x)))
。
谢谢各位。
这里的答案与flip
:-) 相同。OCaml 标准库中没有定义函数组合。在这种情况下,这不是我偶尔想念的东西,我一直想念它。
OCaml Batteries Included项目使用模块中的运算符定义功能组合(按照您给出的顺序-|
)BatStd
。正如 lukstafi 指出的(见下文),该操作员显然会%
在未来的电池版本中更改为。(我已经在他们的源代码树中验证了这一点。)
我只想补充一点,该运算符相当容易包含,在 F# 中它被简单地定义为:
let (<<) f g x = f(g(x));;
它具有类型签名:val ( << ) : f:('a -> 'b) -> g:('c -> 'a) -> x:'c -> 'b
完全按照您的需要...
(f << g << h) x = f(g(h(x))
所以如果你不需要,你就不需要电池项目
我想补充一点,它看起来的原因<<
是,正如您可能猜到的那样,因为>>
操作员做了相反的事情:
let (>>) f g x = g(f(x));;
(f >> g >> h) x = h(g(f(x))
Core中有Fn.compose
函数,但不是中缀运算符。此外,它是作为常规函数实现的,并且具有运行时开销。
在实践中,使用管道运算符非常方便。它没有直接在编译器中实现的运行时开销(从 4.00 开始)。有关详细信息,请参阅优化的管道运算符。
管道运算符在 Core 中可用作“|>”。所以,你可以重写你的表达式如下:h x |> g |> f
似乎不鼓励使用中缀组合运算符。(见这个讨论)。
你可以写f @@ g @@ h x
而不是f (g (h x)))
.
在Containers(Ocaml 的另一个 stdlib 替代品)中,函数组合运算符被调用%
,可以在CCFun模块中找到:
open Containers
open Fun
let is_zero n = (n = 0)
let nonzeros = List.filter (not % is_zero) [0;1;2;3;0]
也许这可以帮助你。
let identite f = f
let (>>) = List.fold_right identite
测试:
# let f=fun x-> x+1 and
g=fun x-> x*2 and
h=fun x-> x+3;;
# [f;g;h] >> 2;;
- : int = 11