Stack Exchange
Is it possible to create a polymorphic variant type dynamically using modules?
I'm trying to organzine and reuse my reasonML code.  I have model module types that look like the following:
module Diet = {

  type schemaType = [`DietSchema];
  type idType = [`DietId(UUID.t)];

  let schema = `DietSchema;
  type idAsType('a) = [> | idType] as 'a;     
};

module Ingredient = {
  type schemaType = [`IngredientSchema];
  type idType = [`IngredientId(UUID.t)];

  let schema = `IngredientSchema;
  type idAsType('a) = [> | idType] as 'a;
};

module Restriction = {
  type schemaType = [`RestrictionSchema];
  type idType = [`RestrictionId(UUID.t)];

  let schema = `RestrictionSchema;
  type idAsType('a) = [> | idType] as 'a;
};

And I would like to generate a types and functions from the idTypes and schemaTypes.
examples are: 
type modelIdType = [
  | Diet.idType
  | Restriction.idType
  | Ingredient.idType
];

type schemaType = [
  | Diet.schemaType
  | Restriction.schemaType
  | Ingredient.schemaType
];

let modelIdToIdFunction = (recordIdType): (schemaType, UUID.t) =>
  switch (recordIdType) {
  | `DietId(uuid) => (Diet.schema, uuid)
  | `RestrictionId(uuid) => (Restriction.schema, uuid)
  | `IngredientId(uuid) => (Ingredient.schema, uuid)
  };

So I'm attempting to construct a module using a functor passing each of the schemas through
module Diet : SchemaType = {
  /* ... */
};

module type SchemaType {
  type schemaType;
  type idType;

  let schema: [> schemaType];
  type idAsType('a) = [> | idType] as 'a;
};

module ProcessSchema = (
  Schema : SchemaType,
  PrevFullSchema : FullSchema
) : (FullSchema) => {
  type id = [> Schema.idType' | PrevFullSchema.id'('a)]  as 'a;
  /* type id = [PrevFullSchema.openId(PrevFullSchema.id) | Schema.idType]; */
  /* type schema = [PrevFullSchema.schema | Schema.schema]; */
  /* type openSchema = [PrevFullSchema.schema | Schema.schema]; */
};

The code above didn't work.  I'm having trouble adding module types to the model modules at the top.  I also attempted through a SchemaType module type but kept hitting The type idType is not a polymorphic variant type,  When I wanted each model to have distinct polymorphic variable types. 
So overall, I want to know if it is possible to create a polymorphic variant type that can be created or extended using modules and functors?
If not is it possible to construct polymorphic variant types using a "list of modules"?
Thanks

In what way does this "clearly" not work? It doesn't compile, but that's because there's several definitions missing, and it's neither clear what you're trying to do, or what problem you're having.  Can you make a [mcve]?

Chances are that the answer is no, though. Creating types dynamically isn't something a statically typed language can typically do. "Static" meaning types are checked at compile-time, and "dynamic" meaning they are checked at run-time. It wouldn't be very safe if you could create types after the checking is done. But perhaps you're using "dynamic" in a different sense here?

Yes, the example above doesn't compile, I guess it may not have been useful to include it.  It was an attempt at building a functor that generates a type for the polymorphic variant.  I think I'm also using the wrong words too.  By "dynamic" I guess I mean "extendable".  I want to extend the type by adding more polymorphic variants.

At which point? And what are you going to do with them? Polymorphic variants are structural, so you can't really "extend" them. When you give it a name it's really just an alias for the type on the right-hand side. Polymorphic variants also support subtyping, so you can specify a polymorphic variant type that says "at least these constructors": [> `this | `that], but this implies a type variable, i.e. it's really [> `this | `that] as 'a.

There's also extensible variants, which are more like ordinary variants, but you have to include a wildcard pattern, which means you lose exhaustiveness checking.

I see you've added a bounty, but I think you'll still need to make an MCVE. The first step to solving a problem is to understand the problem, and it's just not clear, at least to me, what the problem actually is.

Extensible variants does seem to be a good solution thanks.  I'll add an implementation when I have time to come back to this.  Thanks

Someone asked a similar question back in 2002. According to one of the OCaml language developers, it's not possible to dynamically extend polymorphic variant types like that: https://caml-list.inria.narkive.com/VVwLM96e/module-types-and-polymorphic-variants . The relevant bit:


The functor definition is refused because
    "The type M.t is not a polymorphic variant type"
    Is there a workaround?

Not that I know. Polymorphic variant extension only works for known
  closed variant types, otherwise it would not be sound.

The rest of the post has a suggestion which boils down to capturing the new variant types inside different tags, but again that wouldn't work for your use case of dynamically 'adding together' types using a functor.

For the types you can use an extensible variant type. But for the modelIdToIdFunction function given a list of modules I think you can only search through the list, which won't scale.
You should extend the uuid with an ID for each module so you can create a lookup table from module_id to the module from the list for fast access.

I haven't had time to implement but it seems you are correct extensible variant type does seem to be the solution.  I'll update with my implementation of SchemaType  and ProcessSchema later or I'll give an acceptance if someone can show me what they look like.  I'll give this to you because I don't want to waste the bounty points.    Thanks
