OCaml:使用Core Set添加元素的惯用方法是什么?

时间:2016-01-23 00:27:21

标签: 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成为第一个参数。旧的管道风格不再适用于它。

使用Core Set添加元素的惯用方法是什么?

3 个答案:

答案 0 :(得分:3)

不要使用管道来混淆功能应用程序!

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

如果您只想将两个元素添加到集合中,只需写入

即可
Set.(add (add empty a) b)

它非常干净清晰。如果您要添加更多元素, 您可以使用折叠函数来提高可读性:

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

我们可以推测Jane Street正确地改变了Set.add的签名,并将其与List.fold_left一起使用,这是尾递归的,而List.fold_right应该与来自标准库不是尾递归的。

答案 1 :(得分:2)

Jane Street在此blog post中将此设计选项解释为t comes first规则。基本上重点是没有好的选择。有时将t放在第一位,有时最后是有用的。也许他们选择的主要好处是它是一个决定。正如他们在介绍中所述,有时决定的好处是避免浪费时间一直思考这个问题。

更直接地回答你的问题,我会说没有惯用的解决方案。写出任何看似直观的内容。在其他答案中已经给出了一些建议。不要滥用管道操作员。如果要添加的项目更多,请使用fold。我会避免flip;你混淆代码而不会使它更简洁(但我有时也会使用它)。

最后,请注意Core使用标记参数的额外设计选择通常可以完全解决问题。例如,他们的List.fold也首先获取t,但其他参数被标记。因此,您可以将t放在任何您喜欢的位置,使List.fold可用于管道和无管道。所以有人可能会问为什么他们没有签署Set.add t -> elt:elt -> t。好吧,标签也是一个额外的开销;它们会让您输入更多字符。在任何地方使用它们都是极端的,并且他们认为没有标签这个功能更好。

答案 2 :(得分:1)

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

let flip f a b = f b a

然后你可以写:

Set.empty |> flip add elt1 |> flip add elt2

上次检查时,flip在Core中可用Fn.flip

(一般来说,在所有情况下,参数顺序都不是最好的。你最终可能会决定核心顺序对某些事情来说真的很棒。)

相关问题