Reputation: 343
I have the following (fairly abstract) piece of OCaml code, in which the last line gives an error "Syntax error: ')' expected" which is extremely vague for me
module type AT =
sig
type t
end;;
module type BT =
sig
type t
type a
end;;
module A : AT =
struct
type t = int
end;;
module B : BT =
struct
type a
type t = a list
end;;
module type ABT =
sig
type t
module InsideA : AT
module InsideB : BT
end;;
module ABT_Functor (AArg:AT) (BArg:BT with type a = AArg.t) : ABT =
struct
module InsideA = AArg
module InsideB = BArg
type t = Sth of InsideA.t * InsideB.t
end;;
module ABTA = ABT_Functor (A);;
module ABTAB = ABT_Functor (A) (B:BT with type a = A.t);;
However, when I change the last line to
module ABTAB = ABT_Functor (A) (B);;
I get a signature mismatch error, saying
Modules do not match:
sig type t = B.t type a = B.a end
is not included in
sig type t type a = A.t end
Type declarations do not match:
type a = B.a
is not included in
type a = A.t
But I don't really understand that error. So, I hope it's quite clear what I want to achieve - I'd like to provide structures A and B to ABT_Functor functor, to obtain a structure ABTAB. How should I do that?
Upvotes: 1
Views: 969
Reputation: 36118
Hm, your original version does not type-check either (the last line does not even parse), and for the same reason.
The reason is simple: in your definition of B
you are implementing a
as follows:
type a
Such a definition produces a distinct abstract type, i.e. a new type that is different from any other type. As a definition (not to be confused with a specification of a type in a signature), such a type is useless for pretty much anything but phantom types, because you cannot actually create any values of this type.
Nor can you change the definition of the type after the fact. This:
module Bint : sig type a = int end = B
is already ill-typed. Type B.a
was defined as different from int
. It only equals itself.
The problem you see with your functor application follows from there.
Upvotes: 1
Reputation: 14750
The general issue is that there are no constraints between module types AT and BT from the start, but you explicitely require one for your functor, so you need to provide one explicitely when using it if you force the module arguments to their minimal signatures.
In your precise case, the module A
and B
have been coerced respectively to AT
and BT
, without any additional information, thus making their inner types abstract. When passing them to the functor, even with additional type constraints, you cannot recover the implicitly existing relationship between A
and B
as it has been erased.
module A: AT with type t = int = struct type t = int end
module B: BT with type a = int = struct type a = int type t = int list end
(* with these definitions, you may use A and B without further ado as arguments to your functor *)
module ABTAB = ABT_Functor(A)(B) (* it works *)
Note that if you had not constrained A
and B
to begin with, it would have worked straight away.
module A = struct type t = int end
module B = struct type a = int type t = int list end
(* no constraints above *)
module ABTAB = ABT_Functor(A)(B)
Upvotes: 2