2017-05-18 9 views
3
type ('a, 'r) loop 
type 'e task 
type ('a, 'e) tmpl' 

module type COMPONENT = 
sig 
    type t 
    type event 
    type r 

    val update : t -> event -> r 
    val view : (t, event) tmpl' 
end 

module type MAIN_COMPONENT = 
sig 
    type t 
    type event 
    type r 

    include COMPONENT 
     with type t := t 
     with type event := event 
     with type r := (t * event task option, r) loop 
end 

タイプr代用しようとしているときに、私はこのエラーを取得しています:OCamlの破壊的な置換誤り

Error: Only type constructors with identical parameters can be substituted.

をしかし、これは動作します:

module type MAIN_COMPONENT = 
sig 
    type t 
    type event 
    type r 
    type r' = (t * event task option, r) loop 

    include COMPONENT 
     with type t := t 
     with type event := event 
     with type r := r' 
end 

なぜ?

r'タイプを削除するにはどうすればよいですか?

答えて

5

これは破壊的置換の制限です。構文的に同じ型パラメータを持ち、任意の型式ではない型コンストラクタでのみ置き換えることができます。あなたの例で示したように、簡単に回避できるので、基本的な制限ではありません。

しかし、ある種のコードの繰り返しがあります。抽象(タイプレベルで)を使用して取り除くことができます。 OCamlでは、ファンクタを使用して型レベルの抽象化、つまり型と戻り型を取る関数を作成することができます。構文は少し重いですが、適切に選択された名前と署名でうまくいくでしょう。

さんが提供種類t1t2、およびt3からタイプ(t1 * t2 task option, t3) loopを構築しますLoop抽象化を、書いてみましょう:F(T).tは型コンストラクタであるとして

module type T3 = sig type t1 type t2 type t3 end 

module Loop(T : T3) = struct 
    type t = (T.t1 * T.t2 task option, T.t3) loop 
end 

はこの定義を考えると、私たちは、破壊的代入を使用することができますがパラメータなし、たとえば

module type MAIN_COMPONENT = sig 
    type t 
    type event 
    type r 

    module Types : T3 with type t1 = t 
         and type t2 = event 
         and type t3 = r 

    include COMPONENT 
     with type t := t 
     with type event := event 
     with type r := Loop(Types).t 
end 

を定義する必要があるという欠点がありますモジュールは、モジュール署名のファンクタアプリケーションで直接モジュールを構築することができないためです。

もちろん、あなたのケースでは、ソリューションは提案したものよりもはるかに大きいので、おそらく、あなたのものを使用する方が良いでしょう。しかし、定義が大きい場合は、ファンクタを使用することができます。

関連する問題