PTS / CoCの教会でエンコードされたタイプに依存するタイプ


11

私は、Barendregtのラムダキューブの純粋な型システム、特に最も強力なものである構築の計算を実験しています。このシステムにはソート*とがありBOXます。記録のために、以下では、古典的なラムダ計算に近いMorteツールhttps://github.com/Gabriel439/Haskell-Morte-Libraryの具体的な構文を使用しています。

ある種の教会のようなエンコーディング(別名、代数的データ型のBoehm-Berarducci同型)によって帰納型をエミュレートできると思います。簡単な例としてBool = ∀(t : *) -> t -> t -> t、コンストラクタTrue = λ(t : *) -> λ(x : t) -> λ(y : t) -> xとでtypeを使用しますFalse = λ(t : *) -> λ(x : t) -> λ(y : t) -> y

用語レベル関数Bool -> Tの型は、実際には同一性である関数によってProduct T T、古典的なProduct = λ(A : *) -> λ(B : *) -> ∀(t : *) -> (A -> B -> t) -> tモジュロパラメトリック性を持つ型のペアと同型であることがわかりif : Bool -> λ(t : *) -> t -> t -> tます。

以下のすべての質問は依存型の表現についてになるでしょうBool -> *

  1. 私は分割することができるD : Bool -> *のペアにD TrueしてD FalseD再び作成する標準的な方法はありますか?型レベルBool -> T = Product T Tの関数の類似体によって等方性を再現したいのですがif、型のifような引数に種類を渡すことができないため、この関数を元のように単純に書くことはできません。

  2. question(1)を解決するために、2つのコンストラクターを持つ一種の帰納的タイプを使用します。高レベルの説明(Agdaスタイル)は次のタイプです(type-levelの代わりに使用されますif

    data BoolDep (T : *) (F : *) : Bool -> * where
      DepTrue : T -> BoolDep T F True
      DepFalse : F -> BoolDep T F False
    

    PTS / CoCで次のエンコードを使用します。

    λ(T : *) -> λ(F : *) -> λ(bool : Bool ) ->
    ∀(P : Bool -> *) ->
    ∀(DepTrue : T -> P True ) ->
    ∀(DepFalse : F -> P False ) ->
    P bool
    

    上記のエンコードは正しいですか?

  3. 次のBoolDepコードのようなコンストラクタを書き留めることができますDepTrue : ∀(T : *) -> ∀(F : *) -> T -> BoolDep T F True

    λ(T : *) ->  λ(F : *) ->  λ(arg : T ) ->
    λ(P : Bool -> *) ->
    λ(DepTrue : T -> P True ) ->
    λ(DepFalse : F -> P False ) ->
    DepTrue arg
    

しかし、逆関数(または逆方向の関数)を書き留めることはできません。出来ますか?またはBoolDep、同型を生成するために別の表現を使用する必要がありますBoolDep T F True = Tか?


とてもいい質問です。がと等しくなければならない理由を理解するのに苦労してい。定義の展開は、はので、なぜこれらの2つの型は同じである必要がありますか?または、計算でエラーが発生しましたか?ブールT ブールT T * T T T T 製品T T T * T T T T Product T TBoolTBoolT((t:)(ttt))TProductTT(t:)((TTt)t)
ジョルジオモッサ

@Giorgio Mossaはcstheory.stackexchange.com/questions/30923/…を参照してください。-パラメトリック性がある場合(すべてのモデルではなく、初期(構文)モデルにある)、同型性があります。
ZeitRaffer

回答:


9

以下の従来の教会エンコードを使用してこれを行うことはできませんBool

#Bool = ∀(Bool : *) → ∀(True : Bool) → ∀(False : Bool) → Bool

...タイプの(有用な)関数を書くことができないため:

#Bool → *

先ほど述べた*ように、の最初の引数として渡すことができないの#BoolTrueFalse引数が型ではない可能性があるためです。

これを解決するには、少なくとも3つの方法があります。

  1. 帰納的構文の計算を使用します。次に、次のタイプを一般化できます#Bool

    #Bool = ∀(n : Nat) → ∀(Bool : *ₙ) → ∀(True : Bool) → ∀(False : Bool) → Bool
    

    ...そしてにインスタンス化n1ます。つまり*₀、2番目の引数として渡すことができます。

    *₀ : *₁
    

    ...そのため、#Bool2つのタイプの選択に使用できます。

  2. ソートをもう1つ追加します。

    * : □ : △
    

    次に、次の#Bool₂ような別のタイプを定義します。

    #Bool₂ = ∀(Bool : □) → ∀(True : Bool) → ∀(False : Bool) → Bool
    

    これは本質的にCalculus of Inductive構造の特殊なケースですが、#Boolサポートする各種類ごとにの2つの別個の定義を維持する必要があるため、再利用性の低いコードを生成します。

  3. 次の#Bool₂ように、構造計算法内で直接エンコードします。

    #Bool₂ = ∀(True : *) → ∀(False : *) → *
    

変更しないで直接これを使用することが目標の場合、morteアプローチ3のみが機能します。


ご覧のとおり、#Bool₁->#Bool₂を変換することはできませんか?
ZeitRaffer

@ZeitRafferそうです。あなたはから変換することはできません#Bool₁#Bool₂
ガブリエル・ゴンザレス

1
うーん... IIUCは「誘導構造の計算」と呼ばれる無限の型の階層を持つ計算ですが、元のCICにはそのようなものはありませんでした(誘導型をCoCに追加しただけです)。LuoのECC(構造の拡張計算)を考えているかもしれませんか?
ステファン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.