35

只是一个快速的问题。我想知道在标准库(或 Jane Street 的核心或电池中)中定义的 OCaml 中是否有一个中缀函数组合运算符,例如 Haskell 中的 (.) 函数,它为我们节省了很多括号,因为我们可以编写(f . g . h) x而不是不那么吸引人f (g (h x)))

谢谢各位。

4

6 回答 6

30

这里的答案与flip:-) 相同。OCaml 标准库中没有定义函数组合。在这种情况下,这不是我偶尔想念的东西,我一直想念它。

OCaml Batteries Included项目使用模块中的运算符定义功能组合(按照您给出的顺序-|BatStd。正如 lukstafi 指出的(见下文),该操作员显然会%在未来的电池版本中更改为。(我已经在他们的源代码树中验证了这一点。)

据我所知,Jane Street Core项目没有定义函数组合运算符。compose它在Fn模块中定义了一个函数。

于 2013-05-19T16:52:35.547 回答
16

我只想补充一点,该运算符相当容易包含,在 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))
于 2013-10-06T23:03:52.790 回答
14

Core中有Fn.compose函数,但不是中缀运算符。此外,它是作为常规函数实现的,并且具有运行时开销。

在实践中,使用管道运算符非常方便。它没有直接在编译器中实现的运行时开销(从 4.00 开始)。有关详细信息,请参阅优化的管道运算符。

管道运算符在 Core 中可用作“|>”。所以,你可以重写你的表达式如下:h x |> g |> f

于 2013-05-20T12:39:28.497 回答
10

似乎不鼓励使用中缀组合运算符。(见这个讨论)。

你可以写f @@ g @@ h x而不是f (g (h x))).

于 2015-10-12T17:34:09.850 回答
3

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]
于 2016-08-19T08:01:00.213 回答
2

也许这可以帮助你。

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
于 2015-10-12T23:17:27.030 回答