Проблема заключается в полиморфной рекурсии: функция 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)