Bagaimana saya memahami aturan Hindley-Milner?
Hindley-Milner adalah seperangkat aturan dalam bentuk kalkulus sekuens (bukan deduksi alami) yang menunjukkan bahwa kita dapat menyimpulkan jenis (paling umum) dari suatu program dari konstruksi program tanpa deklarasi tipe eksplisit.
Simbol dan notasi
Pertama, mari kita jelaskan simbolnya, dan diskusikan prioritas operator
- 𝑥 adalah pengidentifikasi (secara informal, nama variabel).
- : means adalah jenis (secara informal, instance dari, atau "is-a").
- 𝜎 (sigma) adalah ekspresi yang bisa berupa variabel atau fungsi.
- jadi 𝑥: 𝜎 dibaca " 𝑥 is-a 𝜎 "
- ∈ berarti "adalah elemen dari"
- 𝚪 (Gamma) adalah lingkungan.
- ⊦ (tanda asersi) berarti menegaskan (atau membuktikan, tetapi "menegaskan" secara kontekstual lebih baik.)
- 𝚪 ⊦ 𝑥 : 𝜎 dibaca "𝚪 menyatakan bahwa 𝑥, is-a 𝜎 "
- 𝑒 adalah instance (elemen) aktual dari tipe 𝜎 .
- 𝜏 (tau) adalah tipe: baik dasar, variabel ( 𝛼 ), fungsional 𝜏 → 𝜏 ' , atau produk 𝜏 × 𝜏' (produk tidak digunakan di sini)
- 𝜏 → 𝜏 ' adalah tipe fungsional di mana 𝜏 dan 𝜏' adalah tipe yang berpotensi berbeda.
𝜆𝑥.𝑒 berarti 𝜆 (lambda) adalah fungsi anonim yang mengambil argumen, 𝑥 , dan mengembalikan ekspresi, 𝑒 .
misalkan 𝑥 = 𝑒₀ dalam 𝑒₁ berarti dalam ekspresi, 𝑒₁ , gantikan 𝑒₀ di mana pun 𝑥 muncul.
⊑ berarti elemen sebelumnya adalah subtipe (informal - subkelas) dari elemen yang terakhir.
- 𝛼 adalah variabel tipe.
- ∀ 𝛼.𝜎 adalah tipe, ∀ (untuk semua) variabel argumen, 𝛼 , mengembalikan 𝜎 ekspresi
- ∉ gratis (𝚪) berarti bukan elemen variabel tipe bebas dari 𝚪 yang didefinisikan dalam konteks luar. (Variabel terikat dapat diganti.)
Segala sesuatu di atas garis adalah premis, semua di bawah ini adalah kesimpulan ( Per Martin-Löf )
Diutamakan, dengan contoh
Saya telah mengambil beberapa contoh yang lebih kompleks dari aturan dan menyisipkan tanda kurung berlebihan yang menunjukkan prioritas:
- 𝑥: 𝜎 ∈ 𝚪 dapat ditulis (𝑥: 𝜎) ∈ 𝚪
𝚪 ⊦ 𝑥 : 𝜎 dapat ditulis 𝚪 ⊦ ( 𝑥 : 𝜎 )
𝚪 ⊦ biarkan 𝑥 = 𝑒₀ di 𝑒₁ : 𝜏
setara dengan 𝚪 ⊦ (( biarkan ( 𝑥 = 𝑒₀ ) dalam 𝑒₁ ): 𝜏 )
𝚪 ⊦ 𝜆𝑥.𝑒 : 𝜏 → 𝜏 ' sama dengan 𝚪 ⊦ (( 𝜆𝑥.𝑒 ): ( 𝜏 → 𝜏' ))
Kemudian, ruang besar yang memisahkan pernyataan asersi dan prasyarat lainnya menunjukkan seperangkat prasyarat tersebut, dan akhirnya garis horizontal yang memisahkan premis dari kesimpulan memunculkan akhir urutan prioritas.
Aturan
Berikut ini adalah interpretasi bahasa Inggris dari aturan, masing-masing diikuti oleh pernyataan ulang yang longgar dan penjelasan.
Variabel
Mengingat 𝑥 adalah jenis 𝜎 (sigma), elemen 𝚪 (Gamma),
menyimpulkan conc menegaskan 𝑥 adalah a 𝜎.
Dengan kata lain, dalam 𝚪, kita tahu 𝑥 bertipe 𝜎 karena 𝑥 bertipe 𝜎 dalam 𝚪.
Ini pada dasarnya adalah tautologi. Nama pengenal adalah variabel atau fungsi.
Aplikasi fungsi
Diberikan 𝚪 menegaskan 𝑒₀ adalah tipe fungsional dan 𝚪 menegaskan 𝑒₁ adalah 𝜏
menyimpulkan 𝚪 menegaskan menerapkan fungsi 𝑒₀ ke 𝑒₁ adalah tipe 𝜏 '
Untuk menyatakan kembali aturan, kita tahu bahwa aplikasi fungsi mengembalikan tipe 𝜏 'karena fungsi tersebut bertipe 𝜏 → 𝜏' dan mendapatkan argumen tipe 𝜏.
Ini berarti bahwa jika kita tahu bahwa suatu fungsi mengembalikan tipe, dan kita menerapkannya pada argumen, hasilnya akan menjadi instance dari tipe yang kita tahu itu mengembalikan.
Abstraksi fungsi
Mengingat 𝚪 dan 𝑥 tipe 𝜏 menegaskan 𝑒 adalah tipe, 𝜏 '
menyimpulkan 𝚪 menyatakan fungsi anonim, 𝜆 dari 𝑥 ekspresi balik, 𝑒 adalah tipe 𝜏 → 𝜏'.
Sekali lagi, ketika kita melihat fungsi yang mengambil 𝑥 dan mengembalikan ekspresi 𝑒, kita tahu itu bertipe 𝜏 → 𝜏 'karena 𝑥 (a 𝜏) menyatakan bahwa 𝑒 adalah a 𝜏'.
Jika kita tahu 𝑥 adalah tipe 𝜏 dan dengan demikian ekspresi 𝑒 adalah tipe 𝜏 ', maka fungsi 𝑥 ekspresi kembali 𝑒 adalah tipe 𝜏 → 𝜏'.
Biarkan deklarasi variabel
Mengingat 𝚪 menegaskan 𝑒₀, tipe 𝜎, dan 𝚪 dan 𝑥, tipe 𝜎, menegaskan 𝑒₁ tipe 𝜏
menyimpulkan 𝚪 menegaskan let
𝑥 = 𝑒₀ in
𝑒₁ tipe 𝑒₁
Secara longgar, 𝑥 terikat ke 𝑒₀ dalam 𝑒₁ (a 𝜏) karena 𝑒₀ adalah 𝜎, dan 𝑥 adalah 𝜎 yang menyatakan 𝑒₁ adalah a 𝜏.
Ini berarti jika kita memiliki ekspresi 𝑒₀ yang merupakan 𝜎 (menjadi variabel atau fungsi), dan beberapa nama, 𝑥, juga 𝜎, dan ekspresi 𝑒₁ dari tipe 𝜏, maka kita dapat mengganti 𝑒₀ untuk 𝑥 di mana pun ia muncul di dalam dari 𝑒₁.
Instansiasi
Diberikan 𝚪 menegaskan 𝑒 dari tipe 𝜎 'dan 𝜎' adalah subtipe dari 𝜎
menyimpulkan 𝚪 menegaskan 𝑒 adalah tipe 𝜎
Ekspresi, 𝑒 adalah tipe induk 𝜎 karena ekspresi 𝑒 adalah subtipe 𝜎 ', dan 𝜎 adalah tipe induk 𝜎'.
Jika sebuah instance dari tipe yang merupakan subtipe dari tipe lain, maka itu juga merupakan instance dari tipe-super - tipe yang lebih umum.
Generalisasi
Mengingat 𝚪 menegaskan 𝑒 adalah 𝜎 dan 𝛼 bukan merupakan elemen dari variabel bebas 𝚪,
simpulkan 𝚪 menegaskan 𝑒, ketik untuk semua ekspresi argumen 𝛼 mengembalikan 𝜎 ekspresi
Jadi secara umum, 𝑒 diketik 𝜎 untuk semua variabel argumen (𝛼) yang dikembalikan 𝜎, karena kita tahu bahwa 𝑒 adalah 𝜎 dan 𝛼 bukan variabel bebas.
Ini berarti kita dapat menggeneralisasi suatu program untuk menerima semua jenis argumen yang belum terikat dalam cakupan yang berisi (variabel yang bukan lokal). Variabel terikat ini dapat diganti.
Menyatukan semuanya
Dengan asumsi tertentu (seperti tidak ada variabel bebas / tidak terdefinisi, lingkungan yang diketahui), kita mengetahui jenis-jenis:
- elemen atom dari program kami (Variabel),
- nilai yang dikembalikan oleh fungsi (Aplikasi Fungsi),
- konstruksi fungsional (Abstraksi Fungsi),
- biarkan binding (Biarkan Deklarasi Variabel),
- jenis induk dari instance (Instantiation), dan
- semua ekspresi (Generalisasi).
Kesimpulan
Gabungan aturan ini memungkinkan kami untuk membuktikan jenis paling umum dari program yang dinyatakan, tanpa memerlukan anotasi jenis.