EDIT: Komentar di atas telah memberikan bagian yang hilang. Beberapa orang sengaja bermain dengan bahasa yang kurang lengkap. Secara eksplisit saya tidak peduli dengan bahasa seperti itu. Bahasa tidak lengkap yang benar-benar dapat digunakan adalah hal sulit yang gila untuk desain. Seluruh sisanya memperluas apa yang terjadi mencoba menerapkan teorema ini ke bahasa penuh.
Salah!
function f(a): forall t: Type, t->t
function g(a): forall t: Type, t->t
return (a is g) ? f : a
return a is f ? g : a
di mana is
operator membandingkan dua variabel untuk identitas referensi. Artinya, mereka mengandung nilai yang sama. Bukan nilai yang setara, nilai yang sama. Fungsinya f
dan g
setara dengan beberapa definisi tetapi tidak sama.
Jika fungsi ini dilewatkan dengan sendirinya ia mengembalikan sesuatu yang lain; jika tidak mengembalikan inputnya. Sesuatu yang lain memiliki tipe yang sama seperti itu sendiri sehingga dapat diganti. Dengan kata lain, f
bukan identitas, karena f(f)
kembali g
, sedangkan identitas akan kembali f
.
Untuk memegang teorema itu harus mengasumsikan kemampuan konyol untuk mengurangi
function cantor(n, <z, a>) : forall t: t: Type int, <int, t> -> <int, t>
return n > 1 ? cantor((n % 2 > 0) ? (n + 1) : n / 2, <z + 1, a>) : <z, a>
return cantor(1000, <0, a>)[1]¹
Jika Anda mau berasumsi bahwa Anda dapat mengasumsikan inferensi tipe yang jauh lebih mudah dapat ditangani.
Jika kita mencoba untuk membatasi domain sampai teorema tersebut berlaku, kita akhirnya harus membatasi domain tersebut terlalu jauh.
- Fungsional Murni (tidak ada keadaan bisa berubah, tidak ada IO). OK saya bisa hidup dengan itu. Banyak waktu kami ingin menjalankan bukti atas fungsi.
- Perpustakaan standar kosong. meh.
- Tidak
raise
dan tidak exit
. Sekarang kita mulai dibatasi.
- Tidak ada tipe bawah.
- Bahasa memiliki aturan yang memungkinkan kompiler untuk menutup rekursi tak terbatas dengan menganggapnya harus diakhiri. Kompiler diizinkan untuk menolak rekursi tak terbatas sepele.
- Kompiler dibiarkan gagal jika disajikan dengan sesuatu yang tidak dapat dibuktikan dengan baik.² Sekarang perpustakaan standar tidak dapat mengambil fungsi sebagai argumen. Boo.
- Tidak ada
nil
. Ini mulai bermasalah. Kami sudah kehabisan cara untuk menangani 1 / 0.³
- Bahasa tidak dapat melakukan inferensi tipe cabang dan tidak memiliki penggantian ketika programmer dapat membuktikan inferensi tipe yang tidak dapat dilakukan oleh bahasa. Ini sangat buruk.
Keberadaan kedua kendala terakhir telah melumpuhkan bahasa. Meskipun Turing masih lengkap, satu-satunya cara untuk menyelesaikannya adalah dengan mensimulasikan platform internal yang menafsirkan bahasa dengan persyaratan yang lebih longgar.
¹ Jika menurut Anda kompilator dapat menyimpulkan yang itu, coba yang ini
function fermat(z) : int -> int
function pow(x, p)
return p = 0 ? 1 : x * pow(x, p - 1)
function f2(x, y, z) : int, int, int -> <int, int>
left = pow(x, 5) + pow(y, 5)
right = pow(z, 5)
return left = right
? <x, y>
: pow(x, 5) < right
? f2(x + 1, y, z)
: pow(y, 5) < right
? f2(2, y + 1, z)
: f2(2, 2, z + 1)
return f2(2, 2, z)
function cantor(n, <z, a>) : forall t: t: Type int, <int, t> -> <int, t>
return n > 1 ? cantor((n % 2 > 0) ? (n + 1) : n / 2, <z + 1, a>) : <z, a>
return cantor(fermat(3)[0], <0, a>)[1]
² Bukti bahwa kompiler tidak dapat melakukan ini tergantung pada penyamaran. Kita dapat menggunakan beberapa pustaka untuk memastikan kompiler tidak dapat melihat loop sekaligus. Juga, kita selalu dapat membangun sesuatu di mana program akan bekerja tetapi tidak dapat dikompilasi karena kompiler tidak dapat melakukan induksi dalam memori yang tersedia.
³ Seseorang mengira Anda dapat memiliki pengembalian nihil ini tanpa jenis generik sewenang-wenang yang mengembalikan nihil. Ini membayar penalti yang buruk karena saya tidak melihat bahasa yang efektif yang dapat membayarnya.
function f(a, b, c): t: Type: t[],int,int->t
return a[b/c]
tidak boleh dikompilasi. Masalah mendasar adalah pengindeksan array runtime tidak berfungsi lagi.