在OCaml中,是否可以根据Set定义Map?

时间:2012-04-29 03:52:29

标签: module ocaml functor

我在OCaml中实现了集合(平衡搜索树)的表示。它实际上是签名的Make的仿函数

module Make :
  functor (T : ORDERED_TYPE) ->
sig
  type elt = T.t
  type t
  val empty : t
  val cons : elt -> t -> t
  val delete : elt -> t -> t
  val mem : elt -> t -> bool
  val cardinal : t -> int
end

,其中

 module type ORDERED_TYPE = sig type t val compare : t -> t -> int end

现在我想在标准库中实现像Map这样的字典。它必须有像

这样的签名
 module Make: functor (T : ORDERED_TYPE) -> sig
    type key = T.t
    type +'a t
    ...
 end

其中t是字典的类型。

再次实现平衡搜索树并不优雅,所以我想根据上面实现为仿函数的集来定义字典。我能这样做吗?

4 个答案:

答案 0 :(得分:4)

正如Jeffrey所说,你Set界面的表达力不足以方便地在其上实现Map。通过将集合定义为从键到单位值的映射,从Set实现Map会更简单。

我建议的另一种可能性是首先公开一个没有封装的平衡搜索树模块,其唯一目的是提供一个有效的数据结构,这完全由界面揭示。然后,您可以自由地将其重复用于您喜欢的任何数据结构,包括MapSet,而无需玩游戏来定义另一个数据结构。在这种情况下,这可能不是非常重要(从Set定义Map对于大多数用途来说是合理的),但在我看来,这是一般情况下更好的设计。

简而言之:如果你想重用实现,那么暴露“实现模块”,并在它们之上定义你的“接口模块”。

答案 1 :(得分:3)

在我看来,地图是一个(部分)函数,它是一组有序对。如果您正确定义比较函数,我认为可以完成。您可能必须向Set接口添加一个函数,以便考虑到两个值可以比较等于成员资格但实际上不是相等值的事实。似乎无法使用当前接口为地图定义查找功能。

答案 2 :(得分:2)

正如其他人已经指出的那样,至少有两个原因导致你无法在给定集合之上实现所请求的地图仿函数:

  1. 设置签名无法在给定集合中查找“相等”元素。
  2. 即使它确实存在,也无法以多态方式存储值,因为类型'a map似乎需要。
  3. 您确定该任务要求您在集之上实现地图吗?也许你只是应该实现它们喜欢集?

答案 3 :(得分:0)

嗯,实际上有一个相等的运算符 - 来自有序类型的 compare 函数。

因此,为键/值类型定义您自己的模块,只需要比较关键部分:

module Keyvalue = struct
   type t = ('a * 'b)
   let compare x y = Pervasives.compare (fst x) (fst y)
end

你完成了。现在的问题是,您的 Set 不允许您获取其值;没有 get fold 函数 - 这对于这样的数据结构来说是非常有限的。 如果您被允许使用 Set 实现,则需要添加 get 函数:

module Set = sig
   ...
   get : t -> elt -> elt
end

将返回刚才要求的元素。如果您获取返回元组的第二个元素,则从原始键/值对中获得