module MapHelpers (Ord : Map.OrderedType) = struct
include Map.Make (Ord)
let add_all a b = fold add a b
end
有效,但看似等效
module MapHelpers (Ord : Map.OrderedType) = struct
include Map.Make (Ord)
let add_all = fold add
end
无法使用
进行编译File "Foo.ml", line 2, characters 18-104:
Error: The type of this module,
functor (Ord : Map.OrderedType) ->
sig
...
val add_all : '_a t -> '_a t -> '_a t
end,
contains type variables that cannot be generalized
Command exited with code 2.
并添加显式类型注释
: 'a . 'a t -> 'a t -> 'a t
导致编译提前失败
Error: This definition has type 'a t -> 'a t -> 'a t
which is less general than 'a0. 'a0 t -> 'a0 t -> 'a0 t
为什么添加显式形式a b
会改变这两个模块的输入方式?
答案 0 :(得分:3)
这是价值限制的结果,如以下FAQ项目所述:
A function obtained through partial application is not polymorphic enough
获得“非多态”定义的更常见情况是通过部分应用一般多态函数来定义函数。在Caml中,多态性仅通过“let”构造引入,而应用的结果是弱多态的;因此,应用程序产生的功能不是多态的。在这种情况下,通过清楚地展示类型检查器的功能来恢复完全多态的定义:使用显式功能抽象定义函数,即添加函数构造或额外参数(此重写称为eta-expansion ):
# let map_id = List.map (function x -> x) (* Result is weakly polymorphic *) val map_id : '_a list -> '_a list = <fun> # map_id [1;2] - : int list = [1;2] # map_id (* No longer polymorphic *) - : int list -> int list = <fun> # let map_id' l = List.map (function x -> x) l val map_id' : 'a list -> 'a list = <fun> # map_id' [1;2] - : int list = [1;2] # map_id' (* Still fully polymorphic *) - : 'a list -> 'a list = <fun>
这两个定义在语义上是等价的,并且可以为新定义分配多态类型方案,因为它不再是函数应用程序。
另请参阅this discussion,了解_
中'_a
表示的内容 - 弱,非多态类型变量。