использовать первоклассный модуль в OCaml

module type Arity =
sig 
   val arity : nat (* in my real code it has another type *)
end

module S =
 functor (A : Arity) -> struct
   let check = ...
end

Я хотел бы использовать функцию check внутри функтора S без подписи реализации Arity. Я прочитал первоклассный модуль, но до сих пор не понимаю, как его написать (на практике). Вот мой черновик кода:

let A = has type of (module Arity)

тогда

let M = S (A)

тогда я могу вызвать функцию check с помощью

M.check 

Я пытался:

let f arity = (module (val arity : Arity) : Arity)

он возвращает: val f : (module Arity) -> (module Arity)

Не могли бы вы помочь мне написать этот первоклассный модуль? Могу ли я написать это на Ocaml?

Также в (http://caml.inria.fr/pub/docs/manual-ocaml-4.00/manual021.html#toc81) в разделе 7.14 говорится:

"Выражение модуля (val expr : package-type) не может использоваться в теле функтора, ..."

Я этого не понимаю. Не могли бы вы помочь мне понять, приведя пример?

Спасибо за помощь.


person Quyen    schedule 25.03.2013    source источник


Ответы (1)


Я не совсем понимаю, что вы хотите здесь знать. Видимо, вы запутались в некоторых словах об обычных модулях и функторах OCaml и о более новых «модулях первого класса» OCaml. В любом случае, я даю вам небольшой рабочий пример с OCaml 4.00.1 (не пробуйте с 3.12.1, так как в 4 все улучшено), возможно, это поможет вам:

module type Arity = sig
  val arity :int
end

module S = functor (A : Arity) -> struct
  let check = A.arity = 2 (* or whatever *)
end

Вышесказанное - это то, что вы дали нам с некоторыми тривиальными исправлениями для компиляции. Обычно для использования проверки вы даете реализацию сигнатуры Arity и передаете ее функтору S:

module AR = struct
  let arity = 3
end

module SAR = S(AR)

let () = Printf.printf "%b\n" SAR.check

Воспользуемся первоклассными модулями:

let a = (module AR : Arity)

Это преобразует модуль AR в значение и привяжет его к переменной a. Обратите внимание, что парные скобки являются обязательными для синтаксиса. Также нужно дать сигантуру Arity. Также можно написать так:

let a' : (module Arity) = (module AR)

Итак, тип a и a 'есть (модуль Arity), и вам нужно каким-то образом передать его компилятору. К сожалению, здесь нам не помогает вывод типов.

Вы можете вернуть значение в модуль следующим образом:

module A' = (val a)

Теперь вы также можете создать значение модуля первого класса для функтора S:

module type RESULT = sig
  val check : bool
end

let s (a : (module Arity)) = 
  let module A = (val a) in
  let module SA = S(A) in
  (module SA : RESULT)

Что делает s: принимает значение, возвращает его в модуль, применяет к нему функтор S, а затем создает другое значение из результата применения функтора. Для преобразования необходим знак РЕЗУЛЬТАТ. Вы не можете писать (модуль SA: sig val check bool end). Я не очень разбираюсь в этом, но, как я слышал, типизация значений модуля первого класса является не структурной, а номинальной. Вам нужно дать имя подписи в (модуль M: X).

Тип s: (модуль Arity) -> (модуль RESULT). Применим s к:

let m = s a

Чтобы получить доступ к чеку внутри m, вам нужно вернуть его в модуль:

let m_check =
  let module M = (val m) in
  M.check

Вы можете быть разочарованы, увидев, что преобразование модуля значений ‹-> явное, но вот как это работает ...

person camlspotter    schedule 25.03.2013
comment
Значит, даже если я использую первоклассный модуль или нет, мне нужно определить модуль реализации [AR] для подписи [Arity]? Не так ли? - person Quyen; 25.03.2013
comment
Я этого как раз не понимаю. Вы говорите немодульными словами, я хочу использовать / call [check] внутри функции [let s a = let check = ...] без указания acutual [a]. Мой ответ - нет. Без применения [s] к чему-либо [check] никогда не используется / не вызывается. Но, вероятно, то, что вы имеете в виду под использованием / вызовом, отличается от других. - person camlspotter; 25.03.2013
comment
Я понимаю, потому что мне интересно, есть ли способ получить доступ к функции [check] без реализации [Arity]. Итак, каковы преимущества первоклассного модуля, потому что кажется, что первый метод [модуль SAR = S (AR)] намного проще, чем первоклассный модуль. - person Quyen; 25.03.2013
comment
Модули первого класса - это обычные значения OCaml: вы можете, например, поместить их в списки. В справочнике приведены такие примеры: выбрать разные реализации модулей в зависимости от устройств. Обычные модули не являются первоклассными. Это не ценности, и наши возможности ограничены. - person camlspotter; 25.03.2013