OCaml:使用 Core Set 添加元素的惯用方法是什么?
OCaml: What would be the idiomatic way to add an element using Core Set?
在标准库中,add
函数具有以下签名:
val add : elt -> t -> t
所以我可以使用管道运算符添加元素:
Set.empty |> add elt1 |> add elt2
但是,当我切换到 Core 时,我注意到添加的签名已变为:
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)
非常干净清晰。如果你有更多的元素要添加,
您可以使用 fold-function:
提高可读性
List.fold_left Set.add Set.empty [a; b; c; d; e; f]
我们可以推测 Jane Street 将 Set.add
的签名精确地更改为与 List.fold_left
一起使用,即 tail-recursive,而 List.fold_right
应该与 List.fold_right
一起使用标准库中的集合不是尾递归的。
Jane Street 在 blog post 中将此设计选择解释为 t comes first
规则。基本上关键是没有好的选择。有时将 t
放在最前面有时最后很有用。也许他们选择的主要好处是这是一个决定。正如他们在介绍中所说,有时做决定的好处是避免浪费时间一直思考这个问题。
更直接地回答你的问题,我想说没有惯用的解决方案。写任何你觉得直观的东西。在其他答案中已向您提供了一些建议。不要滥用管道操作员。如果要添加更多项目,请使用 fold
。我会避免 flip
;你混淆了代码而没有使它更简洁(但我有时也会使用它)。
最后,请注意 Core
使用标记参数的额外设计选择通常可以完全解决问题。例如,他们的 List.fold
也首先采用 t
但其他参数被标记。因此,您实际上可以将 t
放在任何您喜欢的地方,从而使 List.fold
在有管道和没有管道的情况下都可用。所以有人会问为什么他们不把 Set.add
的签名设为 t -> elt:elt -> t
。好吧,标签也是一个额外的开销;它们会使您输入更多字符。到处使用它们会很极端,他们认为这个功能没有标签会更好。
在标准库中,add
函数具有以下签名:
val add : elt -> t -> t
所以我可以使用管道运算符添加元素:
Set.empty |> add elt1 |> add elt2
但是,当我切换到 Core 时,我注意到添加的签名已变为:
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)
非常干净清晰。如果你有更多的元素要添加, 您可以使用 fold-function:
提高可读性List.fold_left Set.add Set.empty [a; b; c; d; e; f]
我们可以推测 Jane Street 将 Set.add
的签名精确地更改为与 List.fold_left
一起使用,即 tail-recursive,而 List.fold_right
应该与 List.fold_right
一起使用标准库中的集合不是尾递归的。
Jane Street 在 blog post 中将此设计选择解释为 t comes first
规则。基本上关键是没有好的选择。有时将 t
放在最前面有时最后很有用。也许他们选择的主要好处是这是一个决定。正如他们在介绍中所说,有时做决定的好处是避免浪费时间一直思考这个问题。
更直接地回答你的问题,我想说没有惯用的解决方案。写任何你觉得直观的东西。在其他答案中已向您提供了一些建议。不要滥用管道操作员。如果要添加更多项目,请使用 fold
。我会避免 flip
;你混淆了代码而没有使它更简洁(但我有时也会使用它)。
最后,请注意 Core
使用标记参数的额外设计选择通常可以完全解决问题。例如,他们的 List.fold
也首先采用 t
但其他参数被标记。因此,您实际上可以将 t
放在任何您喜欢的地方,从而使 List.fold
在有管道和没有管道的情况下都可用。所以有人会问为什么他们不把 Set.add
的签名设为 t -> elt:elt -> t
。好吧,标签也是一个额外的开销;它们会使您输入更多字符。到处使用它们会很极端,他们认为这个功能没有标签会更好。