简体   繁体   中英

OCaml: problem with type constructor escaping its scope

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM