Reputation: 8495
Given these module types:
module type CodecTypes = {
type t;
type token;
};
module type Decode = {
include CodecTypes;
let decode: BsGenericParser.Parse.parser(token, t);
};
module type Encode = {
include CodecTypes;
let encode: t => list(token);
};
Is there a way to share the abstract types t
and token
between the two module types?
I tried:
module type Codec = {
include Encode;
include Decode;
}
but the compiler complains about name clashes.
Upvotes: 3
Views: 63
Reputation: 29106
Indeed you can, using signature constraints with destructive substitution:
module type Codec = {
include Encode;
include Decode with type t := t and type token := token;
}
Note that you can also write signature constraints with =
instead of:=
, but this will yield the same error. The difference between them is that =
is a type equality that require the type on both sides to be equal, and :=
will replace ("destructively substitute") the type on the left-hand side. In this case that means Decode.t
is replaced by Encode.t
.
To better illustrate this, consider this example:
module type Codec = {
type u;
include Encode with type t := u;
include Decode with type t := u and type token := token;
}
which will result in the following module type:
module type Codec = {
type u;
type token;
let encode: u => list(token);
let decode: list(token) => u;
};
where t
no longer occurs at all, having been replaced by u
instead.
Upvotes: 3