Saat saya mempelajari Haskell, saya melihat kelas tipenya , yang seharusnya merupakan penemuan hebat yang berasal dari Haskell.
Namun, di halaman Wikipedia tentang kelas tipe :
Pemrogram mendefinisikan kelas tipe dengan menetapkan sekumpulan fungsi atau nama konstanta, bersama dengan tipenya masing-masing, yang harus ada untuk setiap tipe yang termasuk dalam kelas tersebut.
Yang tampaknya agak dekat dengan Antarmuka Java bagi saya (mengutip halaman Antarmuka Wikipedia (Java) ):
Antarmuka dalam bahasa pemrograman Java adalah tipe abstrak yang digunakan untuk menentukan antarmuka (dalam pengertian umum istilah) yang harus diterapkan kelas.
Keduanya terlihat agak mirip: kelas tipe membatasi perilaku tipe, sementara antarmuka membatasi perilaku kelas.
Saya ingin tahu apa perbedaan dan persamaan antara kelas tipe di Haskell dan antarmuka di Java, atau mungkin mereka berbeda secara mendasar?
EDIT: Saya perhatikan bahkan haskell.org mengakui bahwa mereka serupa . Jika mereka sangat mirip (atau apakah mereka?), Lalu mengapa kelas tipe diperlakukan dengan hype seperti itu?
EDIT LEBIH BANYAK: Wow, begitu banyak jawaban bagus! Saya rasa saya harus membiarkan komunitas memutuskan mana yang terbaik. Namun, saat membaca jawaban, semuanya sepertinya hanya mengatakan bahwa "ada banyak hal yang dapat dilakukan kelas tipe sementara antarmuka tidak dapat atau harus mengatasi obat generik" . Saya bertanya-tanya, adakah antarmuka yang dapat dilakukan sementara kelas tipe tidak bisa? Selain itu, saya perhatikan bahwa Wikipedia mengklaim bahwa kelas tipe awalnya ditemukan pada makalah tahun 1989 * "Cara membuat polimorfisme ad-hoc kurang ad hoc", sementara Haskell masih dalam buaiannya, sementara proyek Java dimulai pada tahun 1991 dan pertama kali dirilis pada tahun 1995 Jadi mungkin bukan kelas tipe yang mirip dengan antarmuka, sebaliknya, antarmuka itu dipengaruhi oleh kelas tipe?Apakah ada dokumen / kertas yang mendukung atau menyangkal hal ini? Terima kasih atas semua jawaban, semuanya sangat mencerahkan!
Terima kasih atas semua masukannya!
Jawaban:
Saya akan mengatakan bahwa antarmuka adalah semacam kelas tipe di
SomeInterface t
mana semua nilai memiliki tipet -> whatever
(di manawhatever
tidak mengandungt
). Ini karena dengan jenis hubungan pewarisan di Java dan bahasa serupa, metode yang dipanggil bergantung pada jenis objek tempat mereka dipanggil, dan tidak ada yang lain.Itu berarti sangat sulit untuk membuat hal-hal seperti
add :: t -> t -> t
dengan antarmuka, di mana polimorfik pada lebih dari satu parameter, karena tidak ada cara bagi antarmuka untuk menentukan bahwa tipe argumen dan tipe kembalian metode adalah tipe yang sama dengan tipe dari objek yang dipanggil (yaitu tipe "diri"). Dengan Generics, ada semacam cara untuk memalsukan ini dengan membuat antarmuka dengan parameter generik yang diharapkan memiliki tipe yang sama dengan objek itu sendiri, seperti bagaimanaComparable<T>
melakukannya, di mana Anda diharapkan menggunakanFoo implements Comparable<Foo>
sehinggacompareTo(T otherobject)
jenis memiliki tipet -> t -> Ordering
. Tapi itu tetap mengharuskan programmer untuk mengikuti aturan ini, dan juga menyebabkan sakit kepala ketika orang ingin membuat fungsi yang menggunakan antarmuka ini, mereka harus memiliki parameter tipe generik rekursif.Selain itu, Anda tidak akan memiliki hal-hal seperti
empty :: t
karena Anda tidak memanggil fungsi di sini, jadi ini bukan metode.sumber
Apa yang mirip antara antarmuka dan kelas tipe adalah bahwa mereka menamai dan mendeskripsikan satu set operasi terkait. Operasi itu sendiri dijelaskan melalui nama, masukan, dan keluarannya. Demikian juga mungkin ada banyak implementasi dari operasi ini yang mungkin akan berbeda dalam implementasinya.
Berikut adalah beberapa perbedaan penting:
Secara umum, menurut saya adil untuk mengatakan bahwa kelas tipe lebih kuat dan fleksibel daripada antarmuka. Bagaimana Anda mendefinisikan antarmuka untuk mengonversi string ke beberapa nilai atau contoh dari tipe penerapan? Ini tentu bukan tidak mungkin, tetapi hasilnya tidak akan intuitif atau elegan. Pernahkah Anda berharap itu mungkin untuk mengimplementasikan antarmuka untuk suatu tipe di beberapa perpustakaan yang dikompilasi? Keduanya mudah dicapai dengan kelas tipe.
sumber
Kelas jenis dibuat sebagai cara terstruktur untuk mengekspresikan "polimorfisme ad-hoc", yang pada dasarnya adalah istilah teknis untuk fungsi yang kelebihan beban . Definisi kelas tipe terlihat seperti ini:
Artinya, ketika Anda menggunakan fungsi apply
foo
ke beberapa argumen dari tipe yang termasuk dalam kelasFoobar
, ia mencari implementasifoo
khusus untuk tipe itu, dan menggunakannya. Ini sangat mirip dengan situasi dengan operator overloading dalam bahasa seperti C ++ / C #, kecuali lebih fleksibel dan umum.Antarmuka memiliki tujuan yang sama dalam bahasa OO, tetapi konsep dasarnya agak berbeda; Bahasa OO hadir dengan gagasan built-in dari tipe hierarki yang tidak dimiliki Haskell, yang memperumit masalah dalam beberapa cara karena antarmuka dapat melibatkan overloading dengan subtipe (yaitu, memanggil metode pada contoh yang sesuai, subtipe yang mengimplementasikan antarmuka supertypes mereka lakukan) dan dengan pengiriman berbasis tipe datar (karena dua kelas yang mengimplementasikan antarmuka mungkin tidak memiliki superclass umum yang juga mengimplementasikannya). Mengingat kerumitan tambahan yang sangat besar yang diperkenalkan oleh subtipe, saya sarankan lebih membantu untuk memikirkan kelas tipe sebagai versi perbaikan dari fungsi yang kelebihan beban dalam bahasa non-OO.
Yang juga perlu diperhatikan adalah bahwa kelas tipe memiliki cara pengiriman yang jauh lebih fleksibel - antarmuka umumnya hanya berlaku untuk kelas tunggal yang mengimplementasikannya, sedangkan kelas tipe didefinisikan untuk suatu tipe , yang dapat muncul di mana saja dalam tanda tangan fungsi kelas. Setara dengan ini di antarmuka OO akan memungkinkan antarmuka untuk menentukan cara meneruskan objek kelas itu ke kelas lain, menentukan metode statis dan konstruktor yang akan memilih implementasi berdasarkan apa jenis kembalian yang diperlukan dalam konteks panggilan, menentukan metode yang mengambil argumen dengan tipe yang sama dengan kelas yang mengimplementasikan antarmuka, dan berbagai hal lain yang tidak benar-benar diterjemahkan sama sekali.
Singkatnya: Mereka melayani tujuan yang sama, tetapi cara kerjanya agak berbeda, dan kelas tipe keduanya jauh lebih ekspresif dan, dalam beberapa kasus, lebih mudah digunakan karena bekerja pada tipe tetap daripada potongan dari hierarki pewarisan.
sumber
Saya sudah membaca jawaban di atas. Saya merasa saya bisa menjawab dengan lebih jelas:
Sebuah "kelas tipe" Haskell dan "antarmuka" Java / C # atau "sifat" Scala pada dasarnya analog. Tidak ada perbedaan konseptual di antara keduanya tetapi terdapat perbedaan implementasi:
sumber
Dalam pikiran Master Pemrograman , ada sebuah wawancara tentang Haskell dengan Phil Wadler, penemu kelas tipe, yang menjelaskan kesamaan antara antarmuka di Java dan kelas tipe di Haskell:
Jadi, kelas tipe terkait dengan antarmuka, tetapi korespondensi sebenarnya akan menjadi metode statis parametrized dengan tipe seperti di atas.
sumber
Tonton ceramah Phillip Wadler Faith, Evolution, and Programming Languages . Wadler bekerja di Haskell dan merupakan kontributor utama Java Generics.
sumber
Baca Ekstensi dan Integrasi Perangkat Lunak dengan Kelas Jenis di mana contoh diberikan tentang bagaimana kelas jenis dapat memecahkan sejumlah masalah yang antarmuka tidak bisa.
Contoh yang tertera di koran adalah:
sumber
Saya tidak bisa berbicara dengan level "hype", jika kelihatannya baik-baik saja. Tapi kelas tipe ya mirip dalam banyak hal. Satu perbedaan yang dapat saya pikirkan adalah bahwa Haskell Anda dapat memberikan perilaku untuk beberapa operasi kelas tipe :
yang menunjukkan bahwa ada dua operasi, sama
(==)
, dan tidak sama(/=)
, untuk hal-hal yang merupakan instance dariEq
kelas tipe. Tetapi operasi yang tidak sama didefinisikan dalam istilah yang sama (sehingga Anda hanya perlu memberikan satu), dan sebaliknya.Jadi di Java yang mungkin tidak legal itu akan menjadi seperti ini:
dan cara kerjanya adalah Anda hanya perlu menyediakan salah satu metode tersebut untuk mengimplementasikan antarmuka. Jadi menurut saya kemampuan untuk menyediakan semacam implementasi parsial dari perilaku yang Anda inginkan di tingkat antarmuka adalah suatu perbedaan.
sumber
Mereka serupa (baca: memiliki kegunaan yang sama), dan mungkin diimplementasikan dengan cara yang sama: fungsi polimorfik di Haskell menggunakan sebuah 'vtable' yang mencantumkan fungsi-fungsi yang terkait dengan kelas tipe.
Tabel ini seringkali dapat disimpulkan pada waktu kompilasi. Ini mungkin kurang benar di Jawa.
Tapi ini adalah tabel fungsi , bukan metode . Metode terikat ke sebuah objek, kelas tipe Haskell tidak.
Lihat mereka seperti generik Java.
sumber
Seperti yang dikatakan Daniel, implementasi antarmuka didefinisikan terpisah dari deklarasi data. Dan seperti yang ditunjukkan orang lain, ada cara langsung untuk menentukan operasi yang menggunakan tipe bebas yang sama di lebih dari satu tempat. Jadi mudah untuk didefinisikan
Num
sebagai kelas tipe. Jadi di Haskell kita mendapatkan manfaat sintaksis dari operator yang kelebihan beban tanpa benar-benar memiliki operator ajaib yang kelebihan beban - hanya kelas tipe standar.Perbedaan lainnya adalah Anda dapat menggunakan metode berdasarkan suatu tipe, bahkan ketika Anda belum memiliki nilai konkret dari tipe tersebut yang berkeliaran!
Sebagai contoh,
read :: Read a => String -> a
,. Jadi, jika Anda memiliki cukup informasi jenis lain yang berkeliaran tentang bagaimana Anda akan menggunakan hasil "baca", Anda dapat membiarkan kompilator mencari tahu kamus mana yang akan digunakan untuk Anda.Anda juga dapat melakukan hal-hal seperti
instance (Read a) => Read [a] where...
yang memungkinkan Anda menentukan instance baca apa pun daftar dapat dibaca. Saya rasa itu tidak mungkin di Jawa.Dan semua ini hanyalah kelas tipe parameter tunggal standar tanpa ada tipuan yang terjadi. Setelah kami memperkenalkan kelas tipe multi-parameter, maka dunia kemungkinan baru akan terbuka, dan terlebih lagi dengan dependensi fungsional dan kelompok tipe, yang memungkinkan Anda menanam lebih banyak informasi dan komputasi dalam sistem tipe.
sumber