2011-01-20 13 views
9

OCamlで相互に再帰的なモジュール定義を使用する場合は、.mlファイルでも署名をする必要があります。これは、私が.mliから与えられたインタフェースを公開したいという厄介なことです。私は署名を2回繰り返すことになります。 :(!なぜOCamlで相互に再帰的なモジュールの署名が必要なのですか?

module rec Client : sig 
    type ('serv,'cli) t 

    (* functions ... *) 
end = struct 
    type ('serv,'cli) t = 
    { server: ('serv,'cli) Server.t 
    ; (* other members ... *) 
    } 
end 
and Server : sig 
    type ('serv,'cli) t 

    (* functions ... *) 
end = struct 
    type ('serv,'cli) t = 
    { mutable clients: ('serv,'cli) Client.t list 
    ; mutable state: 'serv 
    } 

    (* functions again ... *) 
end 

これは私がやっているの粗い近似である(Clientタイプのオブジェクトは、それらをインスタンス化Serverを知っている。Server sが彼らのClientのを知っている)。もちろん

、署名があります。.mliで繰り返さなぜこれが必要である

(注:私は文句はないんだけど、実際に型理論または「ハードコンパイラの問題」は、このための関連の理由があるかどうかを知りたい)?

答えて

4

私の推測:再帰的なモジュールをコンパイルするためには、コンパイラは実装のために注釈を入力する必要があります。 mliファイル(使用している場合)では、これらのモジュールのタイプをさらに制限したり、隠したりすることができます。一般的に、コンパイラはタイプ再帰を解決するために有用なタイプを見つけることは期待できません。

+0

それは理にかなっています。確かに、私は '.mli'の外部の消費者に違うタイプのシグネチャを公開することでこの"機能 "を利用しています。私は実現したはずです。 – Ashe

+1

良い推測です。相互に帰納的なモジュールやファンクタの場合の推論は一般的に決めることができないので、型の注釈が必要です。文献には、最小限のアノテーション要件を最適化し、健全性を保持するように型システムを改良する試みがいっぱいです。アノテーション要件の負担を軽減するためにOCamlの型システムを改善できるかどうかは議論の余地があります。 –

7

私が知る限り、これの周りにはこれがありません。非常に高いレベルでは、コンパイラに関する限り、クライアントの型シグネチャはServerの型シグネチャを知るまで不完全であり、その逆もあります。原則として、これを回避する方法があります。コンパイラはコンパイル時に.mliファイルを参照することができます。しかし、そのアプローチには欠点があります。コンパイラとリンカの責任の一部を混在させ、モジュラコンパイルを意図したものではありません。

興味のある方は、再帰的モジュールにXavier Leroyのoriginal proposalをお勧めします。

+0

リンクありがとうございます!タイプ理論は私の少し上ですが、それでも良い読書です。しかし、私はygrekが述べたように、.mliが実際のモジュール自体をコンパイルするのに使われる型を宣言するのではないと思います。あなたが言いましたように、そうしようとすると、それはもっと醜いものになります。 – Ashe

関連する問題