GTDev
GTDev

Reputation: 5528

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

Upvotes: 3

Views: 669

Answers (2)

Yawar
Yawar

Reputation: 11637

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.

Upvotes: 1

Goswin von Brederlow
Goswin von Brederlow

Reputation: 12342

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.

Upvotes: 0

Related Questions