19

在 Python 中,map() 适用于任何遵循序列协议的数据。无论我给它一个字符串还是一个列表甚至是一个元组,它都会做正确的事情^TM。

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

4

4 回答 4

18

最接近这一点的是 OCaml Batteries Included 中的模块Enum以前属于Extlib)。Enum定义地图和折叠Enum.t;您只需要Enum.t为您的数据类型使用与/从的转换。转换可以是相当轻量级的,因为Enum.t它是惰性的。

你真正想要的是 Haskell 风格的类型类,比如FoldableFunctor(它概括了“地图”)。Haskell 库定义了列表、数组和树Foldable的实例。Functor另一种相关技术是泛型编程的“废弃样板”方法。由于 OCaml 不支持类型类或更高种类的多态性,我认为您无法在其类型系统中表达这样的模式。

于 2008-11-06T18:51:48.767 回答
11

OCaml 中主要有两种解决方案:

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

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

如果您不是在寻找那种强大的功能并且只是想要简洁,那么当然,您可以创建一个具有较短名称的模块别名(例如 module S = String)。

于 2009-05-06T11:16:58.820 回答
1

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

于 2008-11-06T19:13:42.593 回答
-3

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

于 2008-11-29T02:58:56.793 回答