Ограничения подтипов в интерфейсах

Я хочу составить несколько «черт» по нескольким модулям. Функция может потребовать несколько таких «черт» в качестве входных данных, то есть:

type 'a x_t = < get_x : int ; .. > as 'a constraint 'a = < get_b : float ; .. >
val foo : x_t -> float 

составление этих трейтов вручную в интерфейсе обременительно и чревато ошибками, но вполне возможно.

Но в идеальном мире я должен иметь возможность использовать имя «черты» вместо того, чтобы вручную составлять все необходимые поля, т.е. писать что-то вроде:

 type 'a x_t = < get_x : int ; .. > as 'a constraint 'a <: a_t

К сожалению, синтаксис OCaml этого не позволяет. Это кажется чисто синтаксическим ограничением, поэтому мне интересно, есть ли для этого более глубокая причина?

Другими словами: почему я не могу напрямую написать ограничения подтипа в сигнатурах типов OCaml?

изменить: Чтобы уточнить вариант использования: у меня есть несколько (иногда взаимозависимых) модулей, которые обеспечивают функциональность в некотором общем общем состоянии. Эти модули должны быть компонуемыми и слабо связанными (т. е. им требуется только их часть глобального состояния для удовлетворения их потребностей, и, таким образом, я всегда могу расширить состояние новыми функциями). Для этого состояние инкапсулируется в объект, который предоставляет несколько линз (выше я использовал только геттеры, а не сеттеры). Следовательно, если я предоставляю определения интерфейса для своих модулей, мне нужно описать требуемые линзы в сигнатуре моих функций через ограничения на параметр типа, который кодирует весь тип состояния. Теперь я ищу способ написать эти составные требования к подписи как можно короче и читабельнее.


person choeger    schedule 30.06.2014    source источник
comment
что такое черта? Вы имеете в виду интерфейс? В OCaml все типы параметров или функций выводятся автоматически. Вы просто используете, а не определяете   -  person Jackson Tale    schedule 30.06.2014
comment
для объяснения черты см. мое редактирование выше. Что касается вывода типов: я знаю об этой функции, но для модульности и удобочитаемости я хочу предоставить подписи модулей OCaml для всех своих модулей.   -  person choeger    schedule 30.06.2014
comment
Ах хорошо. Я думаю, вы говорите о функторах в OCaml. По сути, функтор сам по себе является модулем, который может быть передан другому модулю в качестве параметра. И в этом целевом модуле он может вызывать функции функтора. Лучше, чтобы вы привели краткий пример с вашим вопросом, тогда я смогу продемонстрировать функторы на вашем примере. В противном случае, вот очень хорошее чтение: realworldocaml.org/v1/en/html/functors .html   -  person Jackson Tale    schedule 30.06.2014


Ответы (1)


Если вы определяете свои черты как типы классов, а не как объекты, вы можете использовать синтаксис #foo.

class type b = object
  method get_b : float
end

class type c = object
  method get_c : bool
end

type 'a x_t = < .. > as 'a 
  constraint 'a = #b
  constraint 'a = #c

Вы также можете составлять черты через механизм наследования:

class type e = object
  inherit b inherit c
end

(Похоже, типы слишком умны для своего же блага, но почему бы не поэкспериментировать...)

person gasche    schedule 30.06.2014
comment
Итак, в основном 'a = #b - это синтаксис для ограничений подтипа классов? Есть ли официальная документация по этому синтаксису? Похоже, что в спецификации не упоминается оператор типа #. - person choeger; 30.06.2014
comment
Нотация впервые упоминается в 3.11 полиморфных методах в определении класса intlist. - person didierc; 30.06.2014
comment
Если b является типом класса, то #b является полиморфным типом, экземпляры которого являются точно такими же типами объектов, которые являются экземплярами b. См. руководство. constraint 'a = #b — это всего лишь частный случай constraint 'a = <type expression>. - person gasche; 01.07.2014