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

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

有帮助吗?

解决方案

你最接近的是模块包含OCaml电池的html“rel =”noreferrer“> Enum (以前的 Extlib )。 Enum 通过 Enum.t 定义地图和折叠;您只需使用转换为 Enum.t 作为您的数据类型。转换可能相当轻,因为 Enum.t 是懒惰的。

你真正想要的是Haskell风格的类型类,例如 Foldable Functor (概括了“maps”)。 Haskell库为列表,数组和树定义 Foldable Functor 的实例。另一种相关技术是“Scrap Your Boilerplate”。接近通用编程。由于OCaml不支持类型类或更高级别的多态性,我不认为你可以在它的类型系统中表达这些模式。

其他提示

OCaml有两个主要解决方案:

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

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

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

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top