【问题标题】:overgeneralized curried fns过度概括的咖喱 fns
【发布时间】:2013-05-24 15:36:31
【问题描述】:
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 会改变这两个模块的类型?

【问题讨论】:

标签: ocaml monomorphism


【解决方案1】:

这是值限制的结果,如下面的常见问题项中所述:

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 中的_ 表示的内容——弱、非多态类型变量。

【讨论】:

    猜你喜欢
    • 2014-02-19
    • 1970-01-01
    • 1970-01-01
    • 2018-02-02
    • 1970-01-01
    • 2018-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多