以下划线作为前缀的类型变量告诉我们该变量是弱多态性。弱多态变量只能用于一种类型,但编译器无法推导出确切的类型,因此类型变量带有下划线标记。
当您第一次提供参数时,变量将不再是多态,并且将只能接受单一类型的参数。
通常情况下,函数不是泛化的,但如果它的可能包含可变状态,则标记为弱多态。在你的例子中,这可能是这种情况,因为类型系统不知道List.fold_left
是纯粹还是不纯的函数。
编辑: 为什么避免局部应用(ETA膨胀)允许函数(偶数不纯)是多态性?
让我们定义一个函数,每次函数调用时都会增加一个内部计数器并将其打印出来。在这一点,它需要一个函数作为参数,增加后的反抽应用它:
let count f =
let inc = ref 0 in
(fun x -> inc := !inc + 1; print_int !inc; f x);;
此功能是多态的:('a -> 'b) -> 'a -> 'b
。
接下来,让我们再定义两个函数。理财一周报多态:
let max' = count max;;
val max' : '_a -> '_a -> '_a = <fun>
和多态之一:
let max'' x = count max x;;
val max'' : 'a -> 'a -> 'a = <fun>
现在请注意打印什么,当我们执行这些功能:
max' 1 2;; (* prints 1 *)
max' 1 2;; (* prints 2 *)
max' 1 2;; (* prints 3 *)
max'' 1 2;; (* prints 1 *)
max'' 1 2;; (* prints 1 *)
max'' 1 2;; (* prints 1 *)
所以我们设计为每周多态函数有一个持续可变状态里面允许使用计数器的预期,而多态功能是无状态,并且每次调用都重构,尽管我们想要在里面有一个可变变量。
。这是一个编译器更喜欢可与任何单一类型的,而不是支承全面多态性可以使用弱多态函数的原因。
为什么在函数定义的末尾添加'l'使其具有强多态性? –
是的,这是价值限制。对于像你这样的情况,获得完整多态性的经典方法是“eta扩展”,这正是你在第一个函数中所拥有的。 –
@JeffreyScofield我不明白的是'为什么增加一个额外的参数会使它变得强壮'。 –