在OCaml中,泛型地图上是否存在多态函数?即:
您可以f : 'a list -> bool
作为bool f<T> ([T] x)
您是否还可以使用f : ('k,'v) map -> bool
作为bool f<K,V> (Map<K,V> x)
的等效内容?
如果是这样,类型签名的正确语法是什么,以及如何实现这样的函数(我问,因为map是一个抽象类型,操作它的唯一方法是使用通过调用{ {1}}具体类型)?
由于
答案 0 :(得分:3)
这取决于您使用的通用映射类型,您必须区分两个参数(键的类型和值的类型)。如果使用默认库的Map.Make仿函数,则可以对值的类型进行通用,但是将修复键的类型(通过仿函数实例化):对于给定的密钥模块Key
,module MyMap = Map.Make(Key)
生成的地图只有一个参数'v MyMap.t
,因此您可以拥有f : 'v MyMap.t -> bool
。
还有其他库提供所谓的“多态”映射,其格式为('k, 'v) pmap
,允许对键和值类型进行多态化。但是,这通常以较小的静态保证为代价:如果您以不保留键的顺序的方式更改'k
,则会以编译时无法检测到的方式获得不一致的结果
当然,您可以通过增强Map.Make
仿函数本身(代码未经测试)来实现适用于任何密钥类型的附加功能:
module MyMake(K : Map.OrderedType) = struct
include Map.Make(K)
(* after the "include", all the functions provided by `Map.Make`
are available in the module *)
let is_not_empty m = not (is_empty m)
end
module MyMap = MyMake(String)
let foo = MyMap.is_not_empty (...)
(备注:如果您不需要持久性集合(没有复制/共享/回溯值)并且您不关心最坏情况的复杂性(没有使用暴露于拒绝用户的服务攻击) ,您也可以使用散列表,Hashtbl模块提供('k, 'v) Hashtbl.t
类型。但'k
上的多态性并不存在:您没有得到任何可以使这个变化的函数参数不同)。