Функторы OCaml: : нелогичное поведение

Я экспериментирую с модульным языком OCaml (3.12.1), определяя функторы и сигнатуры для модулей и так далее, в основном следуя примерам из главы 2 руководства по OCaml, и я случайно наткнулся на ситуацию, когда, по-видимому, моя ментальная модель того, как функторы а сигнатуры модулей работают некорректно. Я попытался сузить ситуацию, с которой я столкнулся, до минимально возможного количества кода, поэтому не спрашивайте, чего я пытаюсь добиться, это полностью надуманный пример для демонстрации рассматриваемой функции OCaml.

Итак, у нас есть функтор, который просто предоставляет функцию тождества 'f' и параметризуется модулем, предоставляющим тип входного параметра этой функции. Полностью надуманный пример, как я уже сказал.

module type SOMETYPE = sig type t end ;;
module Identity = functor (Type: SOMETYPE) -> struct let f (x: Type.t) = x end ;;

Учитывая вышеизложенное, мы переходим к определению модуля для предоставления типа int:

module IntType = struct type t = int end ;;

.. а затем используем функтор для генерации модуля для функции идентификации int:

module IdentityInt = Identity(IntType) ;;                     

Конечно же, сгенерированный модуль и его Функция f ведет себя так, как ожидалось:

#IdentityInt.f(3) + 10 ;;
- : int = 13

Ментальная модель функторов как функций, принимающих модули в качестве входных данных и возвращающих модули, кажется, до сих пор служила нам правильно. Функтор Identityожидает в качестве входного параметра модуль сигнатуры (типа модуля) SOMETYPE, и действительно модуль, который мы предоставили ( IntType), имеет правильную сигнатуру, поэтому создается действительный выходной модуль. ( IdentityInt), чья функция fведет себя так, как ожидалось.

Теперь начинается неинтуитивная часть. Что, если мы хотим явно указать, что предоставленный модуль IntTypeдействительно является модулем типа SOMETYPE.Как в:

module IntType : SOMETYPE = struct type t = int end ;;

, а затем сгенерируйте выходной модуль функтора так же, как и раньше:

module IdentityInt = Identity(IntType) ;;

... давайте попробуем использовать функцию fтолько что сгенерированного модуля:

IdentityInt.f 0 ;;

После чего REPL жалуется на:

"Error: This expression [the value 0] has type int but an expression was expected of type IntType.t."

Как предоставление избыточной, но правильной информации о типе может нарушить код? Даже в случае A модуль функтора Identity должен был обрабатывать модуль IntTypeкак тип SOMETYPE. Так почему же явное объявление IntTypeтипом SOMETYPEдает другой результат?

13
задан Marcus Junius Brutus 2 July 2013 в 15:37
поделиться