Pertama, penjelasan terminologis: posisi negatif dan positif datang dari logika. Mereka adalah tentang assymetry di operator logika: di yang berperilaku berbeda dari . Hal serupa terjadi dalam teori kategori, di mana kita mengatakan contravarian dan kovarian bukannya negatif dan positif, masing-masing. Dalam fisika mereka berbicara tentang jumlah yang berperilaku "kovarien" dan "juga contravarian. Jadi ini adalah fenomena yang sangat umum. Seorang programmer mungkin menganggapnya sebagai" input "dan" output ".A BA⇒BAB
Sekarang ke tipe data induktif.
Pikirkan sebuah datatype induktif sebagai semacam aljabar struktur: konstruktor adalah operasi yang mengambil unsur-unsur dari sebagai argumen dan menghasilkan unsur-unsur baru dari . Ini sangat mirip dengan aljabar biasa: penjumlahan mengambil dua angka dan menghasilkan angka.T TTTT
Dalam aljabar, biasanya suatu operasi membutuhkan jumlah argumen yang terbatas, dan dalam kebanyakan kasus dibutuhkan argumen nol (konstan), satu (unary) atau dua (binary). Lebih mudah untuk menggeneralisasi ini untuk konstruktor tipe data. Misalkan c
adalah konstruktor untuk tipe data T
:
- jika
c
konstan kita dapat menganggapnya sebagai fungsi unit -> T
, atau setara (empty -> T) -> T
,
- jika
c
unary kita dapat menganggapnya sebagai fungsi T -> T
, atau yang setara (unit -> T) -> T
,
- jika
c
biner kita dapat menganggapnya sebagai fungsi T -> T -> T
, atau setara T * T -> T
, atau setara (bool -> T) -> T
,
- jika kita menginginkan konstruktor
c
yang mengambil tujuh argumen, kita bisa melihatnya sebagai fungsi di (seven -> T) -> T
mana seven
beberapa tipe yang sebelumnya didefinisikan dengan tujuh elemen.
- kita juga dapat memiliki konstruktor
c
yang mengambil banyak argumen yang tak terhingga banyaknya, yang akan menjadi fungsi (nat -> T) -> T
.
Contoh-contoh ini menunjukkan bahwa bentuk umum dari sebuah konstruktor seharusnya
c : (A -> T) -> T
di mana kita sebut A
dengan arity dari c
dan kita berpikir tentang c
sebagai konstruktor yang mengambil A
argumen -banyak tipe T
untuk menghasilkan unsur T
.
Ini adalah sesuatu yang sangat penting: arities harus didefinisikan sebelum kita mendefinisikan T
, atau kita tidak bisa mengatakan apa yang seharusnya dilakukan oleh konstruktor. Jika seseorang mencoba memiliki konstruktor
broken: (T -> T) -> T
lalu pertanyaan "berapa banyak argumen yang broken
dibutuhkan?" tidak memiliki jawaban yang baik Anda mungkin mencoba menjawabnya dengan "dibutuhkan T
-banyak argumen", tetapi itu tidak akan berhasil, karena T
belum didefinisikan. Kita mungkin mencoba keluar dari cunundrum dengan menggunakan teori titik tetap mewah untuk menemukan jenis T
dan fungsi injeksi (T -> T) -> T
, dan akan berhasil, tetapi kita juga akan melanggar prinsip induksi untuk T
sepanjang jalan. Jadi, itu ide yang buruk untuk mencoba hal seperti itu.
Demi kelengkapan, izinkan saya menjelaskan keseluruhan cerita. Kita perlu menggeneralisasi bentuk konstruktor di atas sedikit. Terkadang kami memiliki operasi atau konstruktor yang mengambil parameter . Sebagai contoh, perkalian skalar mengambil skalar dan vektor untuk menghasilkan vektor . Ini adalah operasi unary pada vektor, diparameterisasi oleh skalar. Kita dapat melihat perkalian skalar sebagai operasi unary yang tak terhingga banyaknya, satu untuk setiap skalar, tapi itu menjengkelkan. Jadi, bentuk umum konstruktor harus memungkinkan parameter dari beberapa tipe :v λ ⋅ vλvλ⋅vc
B
c : B * (A -> T) -> T
Memang, banyak konstruktor dapat ditulis ulang dengan cara ini, tetapi tidak semua, kita perlu satu langkah lagi, yaitu kita harus membiarkan A
untuk bergantung pada B
:
c : (∑ (x : B), A x -> T) -> T
Ini adalah bentuk akhir dari konstruktor untuk tipe induktif. Ini juga tepat apa tipe-W. Bentuknya sangat umum sehingga kita hanya perlu satu konstruktor saja c
! Memang, jika kita memiliki dua dari mereka
d' : (∑ (x : B'), A' x -> T) -> T
d'' : (∑ (x : B''), A'' x -> T) -> T
maka kita bisa menggabungkannya menjadi satu
d : (∑ (x : B), A x -> T) -> T
dimana
B := B' + B''
A(inl x) := A' x
A(inr x) := A'' x
Ngomong-ngomong, jika kita menjelajah bentuk umum kita melihat bahwa itu setara dengan
c : ∏ (x : B), ((A x -> T) -> T)
yang lebih dekat dengan apa yang sebenarnya ditulis orang dalam asisten bukti. Asisten pembuktian memungkinkan kita untuk menuliskan konstruktor dengan cara yang mudah, tetapi itu setara dengan bentuk umum di atas (latihan!).
A
dan akhirnya meledak stack (dalam bahasa berbasis stack).