Мне жаль, что это выглядит как вопрос "пустяков", но это самый минимальный пример, который я могу придумать:
module type Foo = sig
type 'a t
val foo : 'a -> 'a t
end
module Foo : Foo = struct
type 'a t = T of 'a
let foo x = T x
end
(* Rewrap foo, add one function *)
module type Bar = sig
include Foo
val bar : int -> int t
end
module Bar : Bar = struct
include Foo
let bar n = foo (n + 1)
end
(* Specialization of Baz for integers *)
module type Baz = sig
type t
val bar : int -> t
end
module Baz : Baz = struct
type t = int Foo.t
let bar = Bar.bar
end
В этом примере Foo.t
и Bar.t
являются точно такой же тип. Поэтому int Foo.t
- это то же самое, что и int Bar.t
.
. Однако я получаю следующую ошибку компиляции:
File "example.ml", lines 31-34, characters 19-3:
31 | ...................struct
32 | type t = int Foo.t
33 | let bar = Bar.bar
34 | end
Error: Signature mismatch:
Modules do not match:
sig type t = int Foo.t val bar : int -> int Bar.t end
is not included in
Baz
Values do not match:
val bar : int -> int Bar.t
is not included in
val bar : int -> t
File "example.ml", line 28, characters 2-20: Expected declaration
File "example.ml", line 33, characters 6-9: Actual declaration
, если я заменю type t = int Foo.t
, но type t = int Bar.t
, внезапно подборка компиляции. В моем исходном коде у меня много вещей, которые зависят от обоих типов. В моем примере это было бы следующим:
module type Baz = sig
type t
val foo : int -> t
val bar : int -> t
end
module Baz : Baz = struct
type t = int Foo.t
let foo n = Foo.foo n
let bar = Bar.bar
end
Как я могу сказать компиляции, что Foo.t
и Bar.t
одинаковы, не делая их "публично видимыми"?