Я до сих пор не знаю, чего вы пытаетесь достичь, но если ваша цель - реализовать какое-то наследование между вашими модулями (как вы сказали в заголовке какого-то предыдущего потока), вам может понадобиться использовать рекурсивные модули.
Так, например, вы начинаете с определения иерархии модулей: здесь S
- это начальная сигнатура модуля, которая может быть расширена на S1
и S2
:
module type S = sig
type 'a t
end
module type S1 = sig
include S
val f: 'a -> 'a t
end
module type S2 = sig
include S
val g: 'a t -> 'a
end
Затем высоздайте вашу конкретную реализацию, которая точно определяет, что такое 'a t
, и которая реализует все функции, необходимые для S1
и S2
:
module Concrete = struct
type 'a t = 'a array
let f a = [| a |] (* fill with the right contents *)
let g a = a.(0) (* fill with the right contents *)
end
Затем вы абстрагируете тип 'a t
ограничивая реализацию правильными подписями.Здесь вам нужны рекурсивные модули (обратите внимание на ключевое слово rec
):
module rec I : S = Concrete
and I2 : S2 with type 'a t = 'a I.t = Concrete
and I1 : S1 with type 'a t = 'a I.t = Concrete
И вы можете проверить свой результат:
let a = I2.g (I1.f 0)
, который возвращает 0
, как и ожидалось.