4
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にファンクター内の関数を使用したいと思います。私はファーストクラスのモジュールを読みましたが、それを書く方法をまだ理解していません(実際には)。これが私のドラフトコードです:SArity

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)はファンクターの本体では使用できません...」

わかりません。例を挙げて理解するのを手伝っていただけませんか。

ご協力ありがとうございました。

4

1 に答える 1

6

ここで何を知りたいのかよくわかりません。どうやらあなたは通常のOCamlモジュールとファンクターのいくつかの言葉と、むしろOCamlのより新しい「ファーストクラスモジュール」と混同しているようです。とにかく、私はあなたにOCaml 4.00.1での短い作業例を与えます(物事は4で改善されているので3.12.1で試さないでください)、おそらくそれはあなたを助けるでしょう:

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にバインドされます。構文にはparensが必須であることに注意してください。また、巨大なアリティを与える必要があります。次のように書くこともできます。

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を適用してから、ファンクターの適用結果から別の値を作成することです。変換には、singatureRESULTが必要です。書き込むことはできません(モジュールSA:sig val check bool end)。私はこの辺りのことは得意ではありませんが、ファーストクラスのモジュール値の入力は構造的ではなく名目上のものだと聞きました。(モジュールM:X)で署名に名前を付ける必要があります。

sのタイプは(module Arity)->(module RESULT)です。にsを適用してみましょう:

let m = s a

m内のチェックにアクセスするには、モジュールに戻す必要があります。

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

値<->モジュールの変換が明示的であることに失望するかもしれませんが、これがその仕組みです...

于 2013-03-25T04:52:21.757 に答える