誘導型の定義における「保護された」否定的な発生、常に悪いですか?


11

いくつかの否定的な発生がどのように決定的に悪いことができるか知っています:

data False

data Bad a = C (Bad a -> a)

selfApp :: Bad a -> a
selfApp (x@(C x')) = x' x

yc :: (a -> a) -> a
yc f = selfApp $ C (\x -> f (selfApp x))

false :: False
false = yc id

ただし、次のことはわかりません。

  • 負の発生を伴うすべての誘導型は間違った方向に変わる可能性があります。

  • その場合、既知の機械的方法があります。

たとえば、私はこのタイプを間違えさせようと闘ってきました:

type Not a = a -> False

data Bad2 a = C2 (Bad2 (Not a) -> a)

このテーマに関する文献へのポインタをいただければ幸いです。


1
これはCoqですか?ハスケル?擬似型理論?「間違っている」とはどういう意味ですか?
デイブクラーク

@DaveClarke申し訳ありませんが、コードはHaskellですが、否定的な発生が禁止されているCoqやAgdaなどの言語に関する懸念があります。「間違っている」とは、分岐する用語を書くことができることを意味します。したがって、Haskellの例で行ったように、Falseに住むことができます。
Ptival

回答:


10

否定的な発生が禁止されている理由は、Knaster-Tarskiの定理との類推によって理解できます。この定理によれば

場合完備束であり、FはL Lは上で単調関数であるL、その後の固定点の集合Fは、完全な格子です。具体的には、少なくとも固定点がμ F及び最大定点ν fはLf:LLLfμfνf

Lpqqp

Ce:PQQQ

、明らかなことは、Knaster-Tarski定理の一般化を探すことです。そのため、格子上の単調関数の代わりに、オブジェクトにオブジェクトを送信するファンクター F CCが必要ですが、すべてのマップ e P Qがマップ F e Fを取得するように単調性条件を一般化しますP F Q Fがアイデンティティをアイデンティティに送信し、 FがN=μα.1+α F:CCe:PQF(e):F(P)F(Q)F)。F(gf)=F(g)F(f)

あなたは、誘導データ型望むのであれば、必要な不動点が存在することを保証するために、型演算子 Fの項に関数アクションを提供する必要もあります。AgdaとCoqの厳密な陽性条件は、このセマンティック制約を意味する構文条件です。大まかに言って、和と積から型演算子を作成すると、いつでも関数アクションを作成できるため、この方法で作成された型には固定小数点が必要です。μα.F(α)F

依存型の言語では、インデックス付きおよびパラメーター化された型もあるため、実際のタスクはより複雑になります。Bob Atkey(これについてはこちらこちらでブログを書いています)は、ストーリーを探すのに適した場所は次のとおりであると言っています。

Andrejが指摘しているように、基本的に否定的な出来事が大丈夫かどうかは、型理論のモデルに依存します。基本的に、再帰的な定義がある場合、不動点を探しています。数学には不動点定理がたくさんあります。

私が個人的によく利用しているのは、バナッハの不動点定理です。これは、計量​​空間で厳密に収縮する関数を持っている場合、一意の不動点があると言います。このアイデアは(IIRC)Maurice Nivatによってセマンティクスに導入され、アメリカとRuttenによって広く研究され、最近Birkedalと彼の協力者によって「ステップインデックス」と呼ばれる一般的な操作技術に結び付けられました。

これにより、再帰型での負の出現が許可される型理論が生成されますが、特殊な「保護」型コンストラクターで負の出現が発生した場合のみです。このアイデアは中野宏によって導入され、バナッハの定理とのつながりは、私とニック・ベントン、そしてラース・ビルケダルと彼の共著者の両方によってなされました。


7

時には、「運がよければ」再帰方程式を解くことができます。

A(A)A.
  1. AA

    AA1.
    1
  2. A()1

結論:空のタイプ(あなたが呼び出したFalse)とユニットタイプの2つの解決策があります()

A(A2)2,
data Cow a = Moo ((a -> Bool) -> Bool)

A22AA22A

N22N.
2N22NInteger(Integer -> Bool) -> Bool

3

AndrejまたはNeelの説明に何かを追加するのは難しいですが、試してみましょう。説明がより基本的であり、あなたの質問に対してより簡単な答えを与えるので、私は基礎的なセマンティクスを明らかにしようとするのではなく、構文の観点に対処しようとします。

λ

重要なリファレンスは次のとおりです。

メンドラー、N。(1991)。2次ラムダ計算における帰納的な型と型の制約。私は恐れているオンライン参照を見つけていません。ただし、ステートメントと証明は、Naxの博士論文(強くお勧めします!)にあります。

Bad

Bad=BadA

A

λx:Bad.x x:BadA

など

(λx:Bad.x x) (λx:Bad.x x):A

Bad=F(Bad)
F(X)XF(X)

もちろん、等式で定義された型ではなく、コンストラクタで作業しています。つまり、

data Bad = Pack (Bad -> A)

厳密な平等というよりは。ただし、定義できます

unpack :: Bad -> (Bad -> A)
unpack (Pack f) = f

この結果が保持され続けるには十分です:

 (\x:Bad -> unpack x x) (Pack (\x:Bad -> unpack x x))

A


2番目の例では、物事はもう少し複雑です。

Bad=BadA

BadBadBad aBad (Not a)

type Not a = a -> False

data Not a = Not a

Haskellがそのような型定義を許可していれば、簡単に解決できます。

type Acc = Not Acc

この場合、以前とまったく同じ方法でループコンビネーターを構築できます。を使用して同様の(ただし、より複雑な)構造を実行できると思います

data Acc = D (Not Acc)

ここでの問題は、同型を構築することです

Bad Acc <-> Bad (Not Acc)

混合分散に対処する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.