Поскольку тип модуля Exp
определен как
module type Exp = sig type t end
, любое сигнатурное ограничение формы M: Exp
делает M
непригодным для использования, поскольку оно скрывает всю информацию о M, кроме наличия абстрактногоtype Mt Этот абстрактный тип неприменим, поскольку между этим типом и внешним миром нет функций.
Например, это определение модуля определяет тип и сразу скрывает его во внешнем мире:
module TypedExp (TD: IR) : Exp = struct
type t =
{
ty : TD.ty;
descr : TD.exp_descr;
}
end
То, что вы хотели, было просто
module TypedExp (TD: IR) = struct
type t =
{
ty : TD.ty;
descr : TD.exp_descr;
}
end
Если вы действительно хотите добавить ограничение подписи, правильным будет
module TypedExp (TD: IR): sig
type t =
{
ty : TD.ty;
descr : TD.exp_descr;
}
end
= struct
type t =
{
ty : TD.ty;
descr : TD.exp_descr;
}
end
Обратите внимание, что я не использовал Exp with type t = ...
по двум причинам: во-первых, ограничение with
не может определять новые типы.Во-вторых, Exp with type t = ...
- это просто сложный способ написания sig type t = ... end
.
Это основная проблема вашего кода: он скрывает всю информацию, которая позволяет осмысленно манипулировать определенным вами типом.
Например, после удаления ограничения подписи для результата функтора, исправления подписи в рекурсивных ограничениях модуля, упрощения подписи IRprint до
module type IRPrint = sig
type ty
type exp_descr
type exp
val string_of_ty: ty -> string
val string_of_exp_descr: exp_descr -> string
val string_of_exp: exp -> string
end
, тогда функтор TExpPrint
можно исправитьс
module TExpPrint
(E : module type of TExp)
(R: IRPrint with type exp_descr = TIR.exp_descr
and type exp = E.t
and type ty = TIR.ty)
=
struct
open E
let string_of_t e =
R.string_of_exp_descr e.E.descr ^ " " ^ R.string_of_ty e.ty
end
, и я ожидаю, что остальные ошибки последуют, так как становится возможным разделить правильные равенства типов.