Here is the code:
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)
I get this type error (at line 8, characters 17-32):
Error: This expression has type a but an expression was expected of type 'a
The type constructor a would escape its scope
Which is unexpected since the type constructor a
is still in its scope. I expect function foo to have the following type:
foo: (module S with type t = 'a) -> int -> 'a -> 'a
What's wrong?
The issue is polymorphic recursion: the function foo
cannot be polymorphic in its body without explicit annotation. When writing
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)
since the function foo
is not polymorphic in its definition, it cannot reuse the locally abstract type type a
which has been introduced after its own definition.
One way to circumvent this issue is to introduce the recursive function after the locally abstract type:
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 more classical solution is to add an explicit universal quantification to the locally abstract type 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)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.