Haskell memiliki gagasan tentang "fungsi generik" yang memiliki beberapa kemiripan yang jelas dengan common lisp — tidak memiliki pengalaman dengan Haskell atau dengan common lisp, saya mungkin sangat aproksipatif di sini. Ini berarti bahwa seseorang dapat mendefinisikan to_string
fasilitas generik untuk mendefinisikan representasi string untuk semua tipe. Tentu saja, fasilitas harus didefinisikan dalam kasus-kasus khusus tetapi ada to_string
fungsi yang tanda tangannya α → string
.
Apakah jenis terhapus di Haskell, seperti di OCaml? Jika ya, bagaimana implementasi "fungsi generik" di Haskell berbeda dari yang umum, di mana jenisnya dinamis, dan dengan demikian tidak terhapus?
Saya mengerti bahwa detail implementasi spesifik untuk kompiler, tetapi mungkin ada ketentuan umum untuk banyak atau semua implementasi.
sumber
a -> String
. Anda akan lebih cenderung memiliki batasan tipeShow a => a -> String
.Jawaban:
Jawabannya sejauh ini menyesatkan.
Perlu dibuat perbedaan antara polimorfisme "parametrik" dan "ad-hoc overloading". Parametrik berarti "berperilaku seragam untuk semua jenis a", sedangkan "ad-hoc" - yang oleh Simon disebut polimorfik - mengubah implementasi berdasarkan jenisnya.
Contoh keduanya
reverse :: [a] -> [a]
, yang parametrik, danshow :: Show a => a -> String
yang "ad-hoc" kelebihan beban.Jika Anda menginginkan lebih dari intuisi abstrak, saya pikir itu membantu untuk mempertimbangkan kelas kata kerja bahasa alami yang 'berfungsi' untuk semua objek, seperti "memiliki" atau "memikirkan" yang tidak menimbulkan kendala pada objek, tetapi " untuk membuka "membutuhkan apa yang kita bicarakan bisa dibuka. Saya dapat 'memikirkan pintu', dan 'membuka pintu', sementara tidak masuk akal misalnya 'membuka pohon'. Untuk mengambil contoh lebih jauh "membuka" adalah "polimorfik ad-hoc" sebagai "membuka jendela" dan "membuka tiket keluhan dengan layanan pelanggan" adalah dua hal yang sangat berbeda. Jika ini tampaknya dipaksakan - lupakan saja! Ini bekerja untuk saya.
Keduanya diselesaikan pada saat kompilasi, dan pada kenyataannya "dihapus". Modulo berbagai ekstensi GHC dan Template Haskell, dll Jenis yang sebenarnya terhapus pada waktu kompilasi dan tidak pernah diperiksa pada run-time.
Fungsi parametrik polimorfik berperilaku identik untuk semua jenis, sehingga hanya satu bagian kode yang perlu dihasilkan, sedangkan kompiler memutuskan pada waktu kompilasi versi fungsi "jenis-kelas" mana yang perlu dijalankan pada titik program tertentu. Ini juga mengapa ada pembatasan satu instance per tipe per tipe kelas dan work-around "newtype" yang sesuai ada.
Implementasinya dirinci dalam buku teks SPJ dan kertas Wadler dan Blotts pada kelas tipe .
sumber
forall
ekstensi GHC ).peringatan: latar belakang saya di CS tidak terlalu kuat, jadi saya mungkin tidak selalu menggunakan kosa kata yang benar, dan saya mungkin salah pada beberapa poin. Bagaimanapun, inilah pemahaman saya:
Saya pikir Anda membingungkan generik dengan polimorfisme.
Tipe generik seperti
List<Foo>
digunakan untuk menggambarkan tipe yang menggunakan tipe lain sebagai parameter, dan memungkinkan pengecekan tipe yang lebih kaya.Fungsi generik dalam haskell mungkin
count:: List a -> Int
. Ia menerima daftar jenis apa pun, dan mengembalikan jumlah elemen. Hanya ada satu implementasi.Biasanya, ketika mendefinisikan Daftar, Anda tidak dapat mengasumsikan apa pun tentang T. Anda hanya dapat menyimpannya dan mengembalikannya.
to_string
Fungsi Anda adalah fungsi polimorfik, yang artinya akan berperilaku berbeda dalam keadaan yang berbeda. Dalam haskell, ini dilakukan dengan kacamata ketik, yang berfungsi seperti kata sifat untuk jenis.Anda memiliki
Show
typeclass, yang mendefinisikan suatushow :: a -> String
fungsi.Ketika suatu tipe
Foo
mengimplementasikanShow
typeclass, itu harus memberikan definisishow
. Jenis ini kemudian dapat digunakan dalam fungsi yang membutuhkanShow
kualifikasi (seperti padaShow a => a -> whatever
). Haskell tidak dapat menghapus tipe, karena fungsi-fungsi itu harus menemukan implementasishow
fungsi yang benar.sumber