"Terjaga" kejadian negatif dalam definisi tipe induktif, selalu buruk?

11

Saya tahu bagaimana beberapa kejadian negatif dapat benar-benar buruk:

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

Namun, saya tidak yakin apakah:

  • semua tipe induktif dengan kejadian negatif dapat salah;

  • jika demikian, ada cara mekanis yang dikenal untuk melakukannya;

Misalnya, saya telah berjuang untuk membuat jenis ini salah:

type Not a = a -> False

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

Setiap penunjuk ke literatur tentang hal ini akan dihargai.

Ptival
sumber
1
Apakah ini Coq? Haskell? Teori tipe semu? Apa yang Anda maksud dengan "salah"?
Dave Clarke
@DaveClarke Maaf, kodenya adalah Haskell, tetapi perhatiannya lebih pada bahasa seperti Coq atau Agda di mana kejadian negatif dilarang. Dengan "salah", maksud saya bisa menulis istilah yang menyimpang, sehingga bisa menghuni False seperti yang saya lakukan dalam contoh saya di Haskell.
Ptival

Jawaban:

10

Alasan pelarangan kejadian negatif dapat dipahami dengan analogi dengan teorema Knaster-Tarski. Teorema ini mengatakan itu

jika adalah kisi lengkap dan f : L L adalah fungsi monoton pada L , maka himpunan titik tetap f juga merupakan kisi lengkap. Secara khusus, ada setidaknya titik tetap μ f dan terbesar titik tetap ν f .Lf:LLLfμfνf

Dalam teori model tradisional, kisi dapat dilihat sebagai proposisi, dan hubungan keteraturan p q dapat dipahami sebagai entailment (yaitu, bahwa kebenaran q diikuti oleh kebenaran p ).Lpqqp

Ketika kita beralih dari teori model ke teori pembuktian, kisi-kisi menggeneralisasi ke kategori-kategori. Jenis dapat dilihat sebagai objek dari kategori , dan peta e : P Q merupakan bukti yang Q dapat diturunkan dari Q .Ce:PQQQ

Ketika kami mencoba menginterpretasikan tipe yang didefinisikan oleh persamaan rekursif, ee, , hal yang jelas harus dilakukan adalah mencari generalisasi teorema Knaster-Tarski. Jadi, bukannya fungsi monoton pada kisi, kita tahu inginfunctor F : CC , yang mengirimkan objek untuk objek, tetapi generalisasi kondisi monotonicity sehingga setiap peta e : P Q mendapat peta F ( e ) : F ( P ) F ( Q ) (dengan kondisi koherensi yang F mengirimkan identitas ke identitas dan mempertahankan komposisi sehingga FN=μα.1+α F:CCe:PQF(e):F(P)F(Q)F ).F(gf)=F(g)F(f)

Jadi jika Anda menginginkan tipe data induktif , Anda juga perlu menyediakan aksi fungsi dengan syarat untuk operator tipe F agar dapat dipastikan bahwa titik tetap yang Anda inginkan ada. Kondisi positif yang ketat dalam Agda dan Coq adalahkondisisintaksisyang menyiratkanbatasansemantikini. Secara longgar, dikatakan bahwa jika Anda membangun operator tipe dari penjumlahan dan produk, maka Anda selalu dapat memasak tindakan fungsi, dan setiap tipe yang dibentuk dengan cara ini harus memiliki titik tetap.μα.F(α)F

Dalam bahasa yang diketik secara dependen, Anda juga memiliki tipe yang diindeks dan parameter, jadi tugas sebenarnya Anda lebih rumit. Bob Atkey (yang telah membuat blog tentang ini di sini dan di sini ) memberi tahu saya bahwa tempat yang baik untuk mencari ceritanya adalah:

Seperti yang dicatat Andrej, secara mendasar apakah kejadian negatif itu baik atau tidak tergantung pada model teori tipe Anda. Pada dasarnya, ketika Anda memiliki definisi rekursif, Anda mencari titik tetap, dan ada banyak teorema titik tetap dalam matematika.

Salah satu yang saya, secara pribadi, telah banyak gunakan adalah teorema titik tetap Banach, yang mengatakan bahwa jika Anda memiliki fungsi kontraktual ketat pada ruang metrik, maka ia memiliki titik tetap yang unik. Gagasan ini diperkenalkan ke semantik oleh (IIRC) Maurice Nivat, dan dipelajari secara luas oleh Amerika dan Rutten, dan baru-baru ini dihubungkan oleh Birkedal dan rekan-rekannya dengan teknik operasional populer yang disebut "step-indexing".

Ini memunculkan teori tipe di mana kejadian negatif dalam jenis rekursif diizinkan, tetapi hanya ketika kejadian negatif terjadi di bawah konstruktor tipe "penjagaan" khusus. Gagasan ini diperkenalkan oleh Hiroshi Nakano, dan koneksi ke teorema Banach dibuat oleh saya sendiri dan Nick Benton, serta Lars Birkedal dan rekan penulisnya.

Neel Krishnaswami
sumber
7

Kadang-kadang Anda dapat memecahkan persamaan rekursif "dengan keberuntungan".

A(A)A.
  1. AA

    SEBUAHSEBUAH1.
    1
  2. SEBUAH()1

Kesimpulan: ada dua solusi, tipe kosong (yang Anda panggil False) dan tipe unit ().

SEBUAH(SEBUAH2)2,
data Cow a = Moo ((a -> Bool) -> Bool)

SEBUAH22SEBUAHSEBUAH22SEBUAH

N22N.
2N22NInteger(Integer -> Bool) -> Bool
Andrej Bauer
sumber
3

Sulit untuk menambahkan apa pun pada penjelasan Andrej atau Neel, tapi aku akan mencobanya. Saya akan mencoba untuk membahas sudut pandang sintaksis, daripada mencoba mengungkap semantik yang mendasarinya, karena penjelasannya lebih mendasar dan saya memberikan jawaban yang lebih mudah untuk pertanyaan Anda.

λ

Referensi penting adalah sebagai berikut:

Mendler, N. (1991). Tipe induktif dan batasan tipe dalam kalkulus lambda orde kedua. Saya belum menemukan referensi online. Pernyataan dan bukti dapat ditemukan dalam disertasi PhD Nax (bacaan yang sangat direkomendasikan!).

BSebuahd

BSebuahd=BSebuahdSEBUAH

SEBUAH

λx:BSebuahd.x x:BSebuahdSEBUAH

dan sebagainya

(λx:BSebuahd.x x) (λx:BSebuahd.x x):SEBUAH

BSebuahd=F(BSebuahd)
F(X)XF(X)

Tentu saja Anda bekerja bukan dengan tipe yang didefinisikan secara sama tetapi dengan konstruktor , yaitu yang Anda miliki

data Bad = Pack (Bad -> A)

bukan kesetaraan yang ketat. Namun Anda dapat menentukan

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

yang cukup untuk hasil ini untuk terus bertahan:

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

SEBUAH


Dalam contoh kedua Anda, hal-hal sedikit lebih rumit, karena Anda memiliki sesuatu di sepanjang garis

BSebuahd=BSebuahdSEBUAH

BSebuahdBSebuahdBSebuahd SebuahBSebuahd (NHait Sebuah)

type Not a = a -> False

dengan

data Not a = Not a

Akan mudah dipecahkan jika Haskell mengizinkan definisi tipe seperti itu:

type Acc = Not Acc

Dalam hal ini, Anda bisa membuat kombinator pengulangan dengan cara yang persis sama seperti sebelumnya. Saya menduga Anda dapat menggunakan konstruksi yang serupa (tetapi lebih kompleks)

data Acc = D (Not Acc)

Masalahnya di sini adalah membangun isomorfisme

Bad Acc <-> Bad (Not Acc)

Anda harus berurusan dengan varians campuran.

cody
sumber