OCaml是否具有通用map()/ reduce()函数?

时间:2008-11-06 17:35:37

标签: map polymorphism ocaml reduce

在Python中,map()适用于序列协议之后的任何数据。无论我是用字符串还是列表,甚至是元组,它都能做出正确的事情。

我不能在OCaml吃蛋糕吗?除了查看我正在使用的集合类型并查找相应的List.map或Array.map或Buffer.map或String.map之外,我真的别无选择吗?其中一些甚至不存在!我要求的是不寻常的吗?我一定错过了什么。

4 个答案:

答案 0 :(得分:18)

您最接近的是Enum(以前为OCaml Batteries Included)中的模块ExtlibEnum定义Enum.t上的地图和折叠;您只需使用转换到/ Enum.t作为您的数据类型。转换可能相当轻,因为Enum.t是懒惰的。

你真正想要的是Haskell风格的type classes,如FoldableFunctor(概括为“地图”)。 Haskell库为列表,数组和树定义FoldableFunctor的实例。另一个相关技术是"Scrap Your Boilerplate" approach到泛型编程。由于OCaml不支持类型类或higher-kinded polymorphism,我认为你不能在它的类型系统中表达这样的模式。

答案 1 :(得分:11)

OCaml有两个主要解决方案:

  1. Jacques Garrigue几年前已经为许多数据结构实现了语法轻,但效率低的方法。您只需将集合包装在提供map方法的对象中。然后你可以collection#map使用map函数进行任何类型的集合。这比您的要求更通用,因为它允许在运行时替换不同类型的数据结构。但是,这在实践中并不是很有用,因此这种方法从未被广泛采用。

  2. 语法较重但高效,健壮且静态的解决方案是使用仿函数通过您正在使用的数据结构对代码进行参数化。这使得使用不同的数据结构重用代码变得微不足道。有关一些很好的例子,请参阅Markus Mottl的Okasaki的书“Purely Functional Data Structures”的OCaml翻译。

  3. 如果您不是在寻找那种力量而只是想要简洁,那么当然,您可以创建一个名称较短的模块别名(例如模块S = String)。

答案 2 :(得分:1)

问题是每个容器都有不同的表示形式,并且需要不同的map / reduce代码来迭代它。这就是为什么有单独的功能。大多数语言都为容器提供了某种通用接口(例如你提到的序列协议),因此map / reduce之类的函数可以抽象地实现,但是对于你提到的类型却没有这样做。

答案 3 :(得分:-3)

只要在模块中定义类型t和val比较(:t-> t-> int),Map.Make就会为您提供所需的地图。