假设我想索引集合的所有元素并将此索引存储在地图中。一个可行的解决方案是扩展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并且该模块在函数中是本地绑定的,但有没有办法使用第一类模块编写函数?
答案 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)中的索引 - 地图不提供哪些功能。
使用数组会更容易描述,更容易实现,并为相同的性能提供更多功能:这是一个干净的胜利。