过度概括的咖喱 fns [英] overgeneralized curried fns
问题描述
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
会改变这两个模块的类型?
Why does adding the explicit formals a b
change the way these two modules are typed?
推荐答案
这是值限制的结果,如以下常见问题解答项所述:
This is a consequence of the value restriction, as described in the following FAQ item:
获得不够多态"定义的更常见情况是通过一般多态函数的部分应用来定义函数.在 Caml 中,多态性仅通过let"构造引入,应用程序的结果是弱多态性;因此应用程序产生的功能不是多态的.在这种情况下,您可以通过向类型检查器清楚地展示功能来恢复完全多态的定义:使用显式函数抽象定义函数,即添加函数构造或额外参数(这种重写称为 eta-expansion):
The more common case to get a ``not polymorphic enough'' definition is when defining a function via partial application of a general polymorphic function. In Caml polymorphism is introduced only through the "let" construct, and results from application are weakly polymorph; hence the function resulting from the application is not polymorph. In this case, you recover a fully polymorphic definition by clearly exhibiting the functionality to the type-checker : define the function with an explicit functional abstraction, that is, add a function construct or an extra parameter (this rewriting is known as 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>
这两个定义在语义上是等价的,新的定义可以分配一个多态类型方案,因为它不再是一个函数应用程序.
The two definitions are semantically equivalent, and the new one can be assigned a polymorphic type scheme, since it is no more a function application.
另请参阅此讨论,了解'_a
中的_
code> 表示——弱的、非多态的类型变量.
See also this discussion about what the _
in '_a
indicates -- weak, non-polymorphic type variables.
这篇关于过度概括的咖喱 fns的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!