Можно ли динамически создавать полиморфный вариантный тип с помощью модулей?

Я пытаюсь создать журнал и повторно использовать свой код reasonML. У меня есть типы модулей модели, которые выглядят следующим образом:

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;
};

И я хотел бы создать типы и функции из idTypes и schemaTypes.

примеры:

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)
  };

Итак, я пытаюсь построить модуль, используя функтор, передающий каждую из схем через

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]; */
};

Код выше не работал. У меня проблемы с добавлением типов модулей к модулям модели вверху. Я также пробовал использовать тип модуля SchemaType, но продолжал нажимать The type idType is not a polymorphic variant type, когда я хотел, чтобы каждая модель имела разные типы полиморфных переменных.

Итак, в целом, я хочу знать, можно ли создать полиморфный вариантный тип, который можно создать или расширить с помощью модулей и функторов?

Если нет, можно ли построить полиморфные вариантные типы, используя «список модулей»?

Спасибо


person GTDev    schedule 01.12.2018    source источник
comment
Чем это явно не работает? Он не компилируется, но это потому, что отсутствует несколько определений, и непонятно, что вы пытаетесь сделать или какая у вас проблема. Можете ли вы создать минимальный воспроизводимый пример?   -  person glennsl    schedule 02.12.2018
comment
Впрочем, скорее всего, ответ отрицательный. Статически типизированный язык обычно не умеет создавать динамические типы. Типы со статическим значением проверяются во время компиляции, а динамическое значение - во время выполнения. Было бы небезопасно, если бы вы могли создавать типы после завершения проверки. Но, может быть, вы здесь используете динамику в другом смысле?   -  person glennsl    schedule 02.12.2018
comment
Да, приведенный выше пример не компилируется, я полагаю, что, возможно, было бесполезно включать его. Это была попытка построить функтор, который генерирует тип для полиморфного варианта. Думаю, я тоже использую неправильные слова. Под динамическим я подразумеваю расширяемый. Я хочу расширить тип, добавив больше полиморфных вариантов.   -  person GTDev    schedule 02.12.2018
comment
В какой момент? И что ты собираешься с ними делать? Полиморфные варианты являются структурными, поэтому вы не можете их расширить. Когда вы даете ему имя, на самом деле это просто псевдоним для типа с правой стороны. Полиморфные варианты также поддерживают подтипирование, поэтому вы можете указать тип полиморфного варианта, который говорит, по крайней мере, эти конструкторы: [> `this | `that], но это подразумевает переменную типа, т.е. это действительно [> `this | `that] as 'a.   -  person glennsl    schedule 02.12.2018
comment
Также существуют расширяемые варианты, которые больше похожи на обычные варианты, но вы должны включить шаблон подстановки, что означает потерю проверки полноты.   -  person glennsl    schedule 02.12.2018
comment
Я вижу, вы добавили награду, но я думаю, что вам все равно нужно будет пройти MCVE. Первым шагом к решению проблемы является понимание проблемы, и просто не ясно, по крайней мере, для меня, в чем проблема на самом деле.   -  person glennsl    schedule 04.12.2018
comment
Расширяемые варианты кажутся хорошим решением. Я добавлю реализацию, когда у меня будет время вернуться к этому. Спасибо   -  person GTDev    schedule 10.12.2018


Ответы (2)


Кто-то задал похожий вопрос еще в 2002 году. По словам одного из разработчиков языка OCaml, невозможно динамически расширять полиморфные вариантные типы следующим образом: https://caml-list.inria.narkive.com/VVwLM96e/module-types-and-polymorphic-sizes. Соответствующий бит:

В определении функтора отказано, потому что «Тип M.t не является полиморфным вариантным типом». Есть ли обходной путь?

Не знаю. Расширение полиморфных вариантов работает только для известных типов закрытых вариантов, иначе оно не было бы правильным.

В остальной части поста есть предложение, которое сводится к захвату новых типов вариантов внутри разных тегов, но опять же, это не сработает для вашего варианта использования динамического «сложения вместе» типов с помощью функтора.

person Yawar    schedule 12.12.2018

Для типов можно использовать расширяемый вариантный тип. Но для функции modelIdToIdFunction с учетом списка модулей, я думаю, вы можете выполнять поиск только по списку, который не масштабируется.

Вы должны расширить uuid идентификатором для каждого модуля, чтобы вы могли создать таблицу поиска от module_id до модуля из списка для быстрого доступа.

person Goswin von Brederlow    schedule 07.12.2018
comment
У меня не было времени реализовать, но похоже, что вы правы, расширяемый вариантный тип действительно кажется решением. Я обновлю свою реализацию SchemaType и ProcessSchema позже или дам согласие, если кто-нибудь покажет мне, как они выглядят. Я отдам это тебе, потому что не хочу тратить зря очки за награду. Спасибо - person GTDev; 10.12.2018