OCaml:使用核心集添加元素的惯用方法是什么?

OCaml:使用核心集添加元素的惯用方法是什么?,ocaml,ocaml-core,Ocaml,Ocaml Core,在标准库中,add函数具有以下签名: val add : elt -> t -> t 因此,我可以使用管道操作符添加元素: Set.empty |> add elt1 |> add elt2 但是,当我切换到Core时,我注意到add的签名已变成: val add : ('a, 'cmp) t -> 'a -> ('a, 'cmp) t 现在set成为第一个参数。旧的管道样式不再适用于它 使用核心集添加元素的惯用方法是什么?在玩了几分钟后,我能想到的最好

在标准库中,
add
函数具有以下签名:

val add : elt -> t -> t
因此,我可以使用管道操作符添加元素:

Set.empty |> add elt1 |> add elt2
但是,当我切换到Core时,我注意到add的签名已变成:

val add : ('a, 'cmp) t -> 'a -> ('a, 'cmp) t
现在set成为第一个参数。旧的管道样式不再适用于它


使用核心集添加元素的惯用方法是什么?

在玩了几分钟后,我能想到的最好方法是使用
flip
反转参数顺序

let flip f a b = f b a
然后你可以写:

Set.empty |> flip add elt1 |> flip add elt2
上次我检查时,
flip
在Core中作为
Fn.flip
提供


(一般来说,没有参数顺序在所有情况下都是最好的。您可能最终决定核心顺序在某些方面确实很好。)

不要使用管道混淆函数应用程序

管道有很好的存在理由,即构建管道,但在您的示例中,您只是滥用和混淆了代码

如果您只想在一个集合中添加两个元素,只需编写

Set.(add (add empty a) b)
它非常干净,清晰可辨。如果要添加更多元素, 您可以通过使用折叠功能提高可读性:

List.fold_left Set.add Set.empty [a; b; c; d; e; f]

我们可以推测Jane Street更改了
集合的签名。添加
精确地将其与
列表一起使用。左折叠
,这是尾部递归,而应该与标准库中的集合一起使用的
列表.fold_right
不是尾部递归的。

Jane Street在这篇文章中解释了这个设计选择,因为
t优先于
规则。基本上,问题是没有好的选择。有时让
t
排在第一位,有时排在最后是很有用的。也许他们选择的主要好处是这是一个决定。正如他们在介绍中所说的那样,有时决策的好处是避免浪费时间一直思考这个问题

更直接地回答你的问题,我认为没有惯用的解决方法。写你觉得直观的东西。在其他的回答中已经给了你一些建议。不要虐待管道操作员。如果有更多项目要添加,请使用
折叠
。我会避免翻转
;您在没有使代码更简洁的情况下混淆了代码(但有时我也会使用它)


最后,请注意,
Core
使用标记参数的额外设计选择通常可以完全解决问题。例如,它们的
List.fold
也会首先使用
t
,但其他参数都会被标记。因此,您实际上可以将
t
放在任何您喜欢的地方,从而使
列表。fold
在有管道和无管道的情况下都可用。因此,有人可能会问,为什么他们没有设置
的签名。添加
be
t->elt:elt->t
。嗯,标签也是额外的开销;它们会使您键入更多字符。在任何地方使用它们都是极端的,他们认为没有标签这个功能更好。

只是简单的
设置。添加设置项目
(我相信问题是当有几个项目要添加时,如何把事情安排得很好。)@JeffreyScofield是的,我使用旧的简单方式时,我的代码看起来像是一团糟。我很好奇他们为什么要更改签名。@Jackddddd他们更改签名是因为他们想这样做。OCaml stdlib的某些部分没有那么好的签名。