使用第一类模块索引集合

时间:2014-09-30 18:31:31

标签: ocaml

假设我想索引集合的所有元素并将此索引存储在地图中。一个可行的解决方案是扩展Set模块并创建一个内部仿函数:

module Make(M : Set.S) = struct
  include M

  module MakeIndexer(MM : Map.S with type key = elt) = struct
    let index_set set =
      let aux el (ix, acc) =
        (ix + 1, MM.add el ix acc)
      in
      M.fold aux set (0, MM.empty) |> snd
  end
end

现在,使用内部仿函数有点麻烦,我想使用一流模块实现。到目前为止,我得到了以下内容:

module Make(M : Set.S) = struct
  include M

  let index_map (module MM : Map.S with type key = elt) set =
    let aux el (ix, acc) =
      (ix + 1, MM.add el ix acc)
    in
    M.fold aux set (0, MM.empty) |> snd
end

我收到以下错误消息

Characters 156-191:
  M.fold aux set (0, MM.empty) |> snd
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error: This expression has type int MM.t
      but an expression was expected of type int MM.t
      The type constructor MM.t would escape its scope

我知道我正在使用syatic sugar并且该模块在函数中是本地绑定的,但有没有办法使用第一类模块编写函数?

2 个答案:

答案 0 :(得分:0)

更新版本

如果我理解正确,你想让索引图算法多态w.r.t到映射结构。实际上,从整个Map操作集中只需要两件事:初始值和加法运算符。所以你可以把它们作为参数传递给你的函数。

module Make(T : Set.OrderedType) = struct
  module Set = Set.Make(T)

  let index_map (set : Set.t) (map : 'm) add : 'm =
    let aux el (ix, acc) =
      (ix + 1, add el ix acc) in
    Set.fold aux set (0, map) |> snd
end

答案 1 :(得分:-1)

使用数组

  

假设我想索引集合的所有元素并将此索引存储在地图中。

您的解决方案过于复杂。

您应该使用包含集合元素的数组。如果它按递增顺序排序,那么您可以在 O(log n)中找到项目的索引 - 这与地图提供的一样好 - 您可以找到绑定到的项目 O(1)中的索引 - 地图不提供哪些功能。

使用数组会更容易描述,更容易实现,并为相同的性能提供更多功能:这是一个干净的胜利。

相关问题