Reputation: 6175
I'd like to write a module (in Ocaml 3.12) able to define a Variant type as an aggregation of existing different types
It could be 0 to N types, so a variable list or set
it could look like this :
type newtype = Type0 of type0 | Type1 of type1 | ... | TypeN of typeN
Of course I want to factorize its creation
First I tried to create a module 'Composite' parameterized by functors :
module Composite ( T0 : sig type t end ) ( T1 : sig type t end ) =
struct
type t = T0.t | T1.t
end
First difficulty : how can I pass a variable list of functors to the 'Composite' module ?
Is this a good way to procede ?
edit1 : Variant allow to define a XOR type definition (it's either T0 ot T1 but not both); how can I define an OR type definition (can be T0 or T1 or both )?
Upvotes: 1
Views: 210
Reputation: 3347
I think the static type system does not allow what you want. The static type system is trying to help you avoid errors that come from using an incorrect type in some function. But here you are trying to define a type that has an unknown *number* of variants. This is not supported in OCAML.
A heterogeneous list, and a tuple with unknown number of elements, are not supported for the same reason.
To your second question: an object cannot be of type "both T1 and T2" where T1 and T2 are unknown types... This concept is incompatible with type checking. If T1 and T2 are compatible types, i.e. T2 is an object type inherited from T1, or T2 is a polymorphic variant type that is an extension of T1, then you can have an object of type T1, and you can also cast T2 to T1. But still there is no concept of "both T1 and T2". What if you have a function that accepts only T1, what should this function do if given an object of type "both T1 and T2" but not just "T1"? I think there is no answer.
Although these things are not supported in OCAML, you can probably design your types in a different way, so that the type system of OCAML accepts your code. The type system of OCAML is very flexible, and it will then be able to help you avoid errors in your code!
Upvotes: 1
Reputation: 5048
If want a "flat" composite type and get the union of constructors, the only way is to use polymorphic variants (as stated by @lukstafi in the comments), but in this case t1 and t2 cannot be abstract:
type t1 = [ `A of int | `B of string | `C of float ]
type t2 = [ `B of string | `C of float | `D of char ]
type t3 = [ t1 | t2 ]
If you really want to use modules you have to loose your flat representation and thus you will have a disjoint union:
module Composite ( T0 : sig type t end ) ( T1 : sig type t end ) =
struct
type t = T0 of T0.t | T1 of T1.t
end
Upvotes: 5