代码如下:
module type S = sig
type t
val do_it: t -> int -> t
end
let rec foo (type a) (module Foo:S with type t=a) (i:int) (x:a) =
if i=0 then x
else foo (i-1) (Foo.do_it x i)
我收到此类型错误(在第8行,字符17-32):
Error: This expression has type a but an expression was expected of type 'a
The type constructor a would escape its scope
这是意外的,因为类型构造函数a
仍在其范围内。我希望函数foo具有以下类型:
foo: (module S with type t = 'a) -> int -> 'a -> 'a
怎么了?
答案 0 :(得分:3)
问题是多态递归:函数foo
的主体在没有显式注释的情况下不能是多态的。写作时
let rec foo (type a) (module Foo:S with type t=a) (i:int) (x:a) =
if i=0 then x
else foo (module Foo:S with type t = a) (i-1) (Foo.do_it x i)
由于函数foo
的定义不是多态的,因此它无法重用在其自己的定义之后引入的局部抽象类型type a
。
规避此问题的一种方法是在局部抽象类型之后引入递归函数:
let foo (type a) =
let rec foo (module Foo:S with type t=a) (i:int) (x:a) =
if i=0 then x
else foo (module Foo) (i-1) (Foo.do_it x i) in
foo
一种更为经典的解决方案是向本地抽象类型a
添加一个显式的通用量化:
let rec foo: type a. (module S with type t=a) -> int -> a -> a =
fun (module Foo) i x ->
if i=0 then x
else foo (module Foo) (i-1) (Foo.do_it x i)