Bisakah inferensi Hindley-Milner bekerja untuk bahasa Go?

22

Saya pernah membaca bahwa Hindley-Milner tidak bekerja dengan sistem tipe yang memiliki subclass, dan ada fitur sistem tipe lain yang juga tidak bekerja dengan baik dengannya. Go saat ini hanya memiliki tipe inferensi yang sangat terbatas di :=operator. Tapi Go tidak memiliki subclass dalam arti tradisional, hanya antarmuka yang sangat mirip dengan kelas tipe Haskell yang bekerja dengan baik dengan inferensi Hindley-Milner.

Jadi, dapatkah inferensi Hindley-Milner bekerja pada prinsipnya untuk Go dengan cara yang sama seperti pada Haskell? Atau apakah Go memiliki fitur lain yang merusaknya? (Di sisi lain, Haskell juga memiliki beberapa fitur yang tidak berfungsi dengan Hindly-Milner, jika Anda menggunakan yang harus Anda ketik secara manual bagian-bagian dari program Anda.)

JanKanis
sumber

Jawaban:

35

Inferensi tipe Hindley-Milner digunakan untuk sistem tipe Hindley-Milner, pembatasan sistem tipe System-F. Fitur menarik dari sistem tipe HM adalah mereka memiliki parametrik polimorfisme (alias. Generik). Itu adalah fitur sistem tipe tunggal terbesar yang tidak dimiliki Golang.

Dengan pembatasan yang membuat frustasi, inferensi tipe HM tidak mungkin. Mari kita lihat kode yang tidak diketik:

func f(a) {
  return a.method()
}

Apa jenis f? Kita mungkin melihat bahwa aharus memiliki sebuah metode, sehingga kita bisa menggunakan antarmuka anonim: func f(a interface { method() ??? }) ???. Namun, kami tidak tahu apa tipe pengembaliannya. Dengan variabel tipe, kita bisa mendeklarasikan tipe sebagai

func f[T](a interface{ method() T }) T

Namun, Go tidak memiliki variabel tipe sehingga ini tidak akan berfungsi. Sementara antarmuka implisit membuat beberapa aspek inferensi tipe lebih mudah, kami sekarang tidak memiliki cara untuk mengetahui tipe kembalinya pemanggilan fungsi. Sistem-HM membutuhkan semua fungsi untuk dideklarasikan daripada diimplikasikan, dan setiap nama hanya dapat memiliki tipe tunggal (sedangkan metode Go dapat memiliki tipe yang berbeda di antarmuka yang berbeda).

Sebaliknya, Go mengharuskan fungsi selalu dideklarasikan sepenuhnya, tetapi memungkinkan variabel untuk menggunakan inferensi tipe. Ini dimungkinkan karena sisi kanan dari suatu tugas variable := expressionsudah memiliki tipe yang diketahui pada titik program tersebut. Jenis inferensi jenis ini sederhana, benar, dan linier.

  • Jenis variabel segera dikenal pada titik deklarasi, sedangkan inferensi HM harus berpotensi mengetikkan seluruh program terlebih dahulu. Ini memiliki dampak nyata pada kualitas pesan kesalahan juga.
  • Pendekatan inferensi tipe Go akan selalu memilih tipe yang paling spesifik untuk suatu variabel, berbeda dengan HM yang memilih tipe yang paling umum. Ini berfungsi dengan baik dengan subtyping, bahkan dengan antarmuka implisit Go.
amon
sumber
24
@ bishop Ini "beralasan" untuk nilai "alasan" yang sangat kecil.
hobbs
18
@ bishop Setelah melakukan pekerjaan kompiler dalam bahasa dengan obat generik, saya pasti bisa setuju: sulit untuk mengimplementasikannya tanpa menyulitkan implementasi. Saya bahkan akan mengganti "sulit" dengan "tidak mungkin." Namun, bukan itu intinya; intinya adalah, apakah itu sepadan dengan komplikasi ekstra? Dan jawabannya, bagi siapa saja yang bekerja dengan dan tanpa obat generik, jelas "ya, pasti!" Saya harus setuju dengan sepenuh hati dengan klaim bahwa menolak untuk menerapkan obat generik karena "oh tidak, kompleksitas" itu bodoh.
Mason Wheeler
18
Ini juga mengapa Go devs berpura-pura bahwa segala bentuk FP itu buruk; Go memiliki fungsi kelas pertama dengan penutupan leksikal, dan dengan itu kemampuan untuk membuat fungsi tingkat tinggi, tapi itu tidak mungkin untuk menempatkan mereka untuk penggunaan yang baik karena jenis fungsi dasar seperti map, filter, dan reducesemua yang tak terkatakan dalam Go sangat terbatas jenis sistem.
hobbs
9
@obb And Go bisa menjadi bahasa yang sangat bagus jika itu diperbaiki, tetapi orang-orang harus menulis perpustakaan generasi generik seperti gengendangonerics
cat
14
@ kucing Ini memalukan. Pada mulanya Go tampaknya seperti bahasa yang hebat yang penuh dengan ide-ide hebat, tetapi kemudian Anda menyadari bahwa itu tidak memiliki warisan dan polimorfisme, sehingga Anda tidak dapat melakukan OOP dengan baik, dan tidak memiliki obat generik, sehingga Anda tidak dapat melakukan FP dengan baik, dan Anda dibiarkan menatap kosong ke layar bertanya "lalu bagaimana tepatnya kamu menggunakan bahasa ini?!?"
Mason Wheeler