Saya sedang mengerjakan kompiler kalkulus lambda kecil yang memiliki sistem inferensi tipe Hindley-Milner yang berfungsi dan sekarang juga mendukung rekursif mari (bukan dalam kode tertaut), yang saya pahami harus cukup untuk membuatnya Turing lengkap .
Masalahnya sekarang adalah saya tidak tahu bagaimana membuatnya menjadi daftar dukungan, atau apakah sudah mendukung mereka dan saya hanya perlu menemukan cara untuk menyandikannya. Saya ingin dapat mendefinisikannya tanpa harus menambahkan aturan baru ke sistem tipe.
Cara termudah yang dapat saya pikirkan tentang daftar xadalah sebagai sesuatu yang bisa berupa null(atau daftar kosong), atau pasangan yang mengandung keduanya xdan daftar x. Tetapi untuk melakukan ini saya harus dapat mendefinisikan pasangan dan atau, yang saya percaya adalah produk dan jenis penjumlahannya.
Sepertinya saya bisa mendefinisikan pasangan dengan cara ini:
pair = λabf.fab
first = λp.p(λab.a)
second = λp.p(λab.b)
Karena pairakan memiliki tipe a -> (b -> ((a -> (b -> x)) -> x)), setelah melewati, katakan, an intdan a string, itu akan menghasilkan sesuatu dengan tipe (int -> (string -> x)) -> x, yang akan menjadi representasi dari sepasang intdan string. Apa yang mengganggu saya di sini adalah bahwa jika itu mewakili pasangan, mengapa itu tidak setara dengan logis, atau menyiratkan proposisi int and string? Namun, setara dengan (((int and string) -> x) -> x), seolah-olah saya hanya bisa memiliki tipe produk sebagai parameter untuk fungsi. Jawaban initampaknya mengatasi masalah ini, tetapi saya tidak tahu apa arti simbol yang dia gunakan. Juga, jika ini tidak benar-benar menyandikan jenis produk, apakah ada yang bisa saya lakukan dengan jenis produk yang tidak dapat saya lakukan dengan definisi pasangan saya di atas (mengingat saya juga dapat mendefinisikan n-tuple dengan cara yang sama)? Jika tidak, tidakkah ini akan bertentangan dengan fakta bahwa Anda tidak dapat mengungkapkan kata kata (AFAIK) hanya menggunakan implikasi?
Juga, bagaimana dengan tipe penjumlahan? Bisakah saya menyandikannya menggunakan tipe fungsi saja? Jika demikian, apakah ini cukup untuk mendefinisikan daftar? Atau yang lain, apakah ada cara lain untuk mendefinisikan daftar tanpa harus memperluas sistem tipe saya? Dan jika tidak, perubahan apa yang harus saya lakukan jika saya ingin membuatnya sesederhana mungkin?
Harap diingat bahwa saya adalah pemrogram komputer tetapi bukan ilmuwan komputer atau ahli matematika dan sangat buruk dalam membaca notasi matematika.
Sunting: Saya tidak yakin apa nama teknis dari apa yang telah saya implementasikan sejauh ini, tetapi semua yang saya miliki pada dasarnya adalah kode yang saya tautkan di atas, yang merupakan algoritma pembatas kendala yang menggunakan aturan untuk aplikasi, abstraksi dan variabel yang diambil dari algoritma Hinley-Milner dan kemudian algoritma unifikasi yang mendapatkan tipe utama. Misalnya, ekspresi \a.aakan menghasilkan jenis a -> a, dan ekspresi \a.(a a)akan melempar kesalahan pemeriksaan yang terjadi. Di atas ini, tidak ada letaturan tetapi fungsi yang tampaknya memiliki efek yang sama yang memungkinkan Anda mendefinisikan fungsi global rekursif seperti pseudo-code ini:
GetTypeOfGlobalFunction(term, globalScope, nameOfFunction)
{
// Here 'globalScope' contains a list of name-value pair where every value is of class 'ClosedType',
// meaning their type will be cloned before unified in the unification algorithm so that they can be used polymorphically
tempType = new TypeVariable() // Assign a dummy type to `tempType`, say, type 'x'.
// The next line creates an scope with everything in 'globalScope' plus the 'nameOfFunction = tempType' name-value pair
tempScope = new Scope(globalScope, nameOfFunction, tempType)
type = TypeOfTerm(term, tempScope) // Calculate the type of the term
Unify(tempType, type)
return type
// After returning, the code outside will create a 'ClosedType' using the returned type and add it to the global scope.
}
Kode pada dasarnya mendapatkan jenis istilah seperti biasa, tetapi sebelum menyatukan, ia menambahkan nama fungsi yang didefinisikan dengan tipe dummy ke dalam lingkup tipe sehingga dapat digunakan dari dalam dirinya sendiri secara rekursif.
Sunting 2: Saya baru menyadari bahwa saya juga perlu tipe rekursif, yang tidak saya miliki, untuk mendefinisikan daftar seperti yang saya inginkan.
let func = \x -> (func x)) Anda mendapatkan apa yang saya miliki.