Dalam bertahun-tahun pemrograman OO saya sudah mengerti apa itu serikat yang diskriminatif, tapi saya tidak pernah benar-benar merindukan mereka. Saya baru-baru ini melakukan beberapa pemrograman fungsional dalam C # dan sekarang saya menemukan saya terus berharap saya memilikinya. Ini membingungkan saya karena di hadapannya, konsep serikat yang didiskriminasi tampaknya cukup independen dari dikotomi fungsional / OO.
Apakah ada sesuatu yang inheren dalam pemrograman fungsional yang membuat serikat yang didiskriminasi menjadi lebih berguna daripada di OO, atau apakah dengan memaksa diri saya untuk menganalisis masalah dengan cara yang "lebih baik", saya telah cukup meningkatkan standar saya dan sekarang menuntut yang lebih baik model?
Jawaban:
Serikat yang didiskriminasi benar-benar bersinar bersamaan dengan pencocokan pola, di mana Anda memilih perilaku yang berbeda tergantung pada kasusnya. Tetapi pola ini secara fundamental bertentangan dengan prinsip-prinsip OO murni.
Dalam OO murni, perbedaan perilaku harus didefinisikan oleh tipe (objek) itu sendiri dan dienkapsulasi. Jadi kesetaraan dengan pencocokan pola akan memanggil metode tunggal pada objek itu sendiri, yang kemudian kelebihan beban oleh sub-tipe yang dimaksud untuk mendefinisikan perilaku yang berbeda. Memeriksa jenis objek dari luar (yang dilakukan pencocokan pola) dianggap sebagai antipattern.
Perbedaan mendasar adalah bahwa data dan perilaku terpisah dalam pemrograman fungsional, sedangkan data dan perilaku dirangkum bersama dalam OO.
Inilah alasan historisnya. Bahasa seperti C # berkembang dari bahasa OO klasik ke bahasa multi-paradigma dengan memasukkan lebih banyak fitur fungsi.
sumber
List<A>
metodeB Match<B>(B nil, Func<A,List<A>,B> cons)
. Sebagai contoh, ini adalah pola yang digunakan Smalltalk untuk boolean. Ini juga pada dasarnya bagaimana Scala menanganinya. Beberapa kelas yang digunakan adalah detail implementasi yang tidak perlu diekspos.isEmpty
metode yang memeriksa apakah referensi ke simpul berikutnya adalah nol.Setelah diprogram dalam Pascal dan Ada sebelum belajar pemrograman fungsional, saya tidak mengaitkan serikat yang didiskriminasi dengan pemrograman fungsional.
Serikat-serikat yang didiskriminasi dalam beberapa hal merupakan dual warisan Yang pertama memungkinkan untuk dengan mudah menambahkan operasi pada set tipe tetap (yang ada di serikat pekerja), dan pewarisan memungkinkan untuk dengan mudah menambahkan tipe dengan set operasi tetap. (Cara mudah menambahkan keduanya disebut masalah ekspresi ; itu adalah masalah yang sangat sulit untuk bahasa dengan sistem tipe statis.)
Karena penekanan OO pada jenis, dan penekanan ganda pemrograman fungsional pada fungsi, bahasa pemrograman fungsional memiliki afinitas alami untuk jenis serikat dan menawarkan struktur sintaksis untuk memudahkan penggunaannya.
sumber
Teknik pemrograman imperatif, seperti yang sering digunakan dalam OO, sering bergantung pada dua pola:
null
untuk menunjukkan "tidak ada nilai" atau kegagalan.Paradigma fungsional biasanya menghindari keduanya, lebih suka mengembalikan tipe majemuk yang menunjukkan alasan keberhasilan / kegagalan atau nilai / tidak ada nilai.
Serikat yang didiskriminasi sesuai dengan tagihan untuk tipe majemuk ini. Misalnya, dalam contoh pertama, Anda mungkin kembali
true
, atau beberapa struktur data yang menjelaskan kegagalan. Dalam kasus kedua, penyatuan yang berisi nilai, ataunone
,nil
dll. Kasus kedua sangat umum, bahwa banyak bahasa fungsional memiliki tipe "mungkin" atau "opsi" untuk mewakili nilai / tidak ada penyatuan tersebut.Saat beralih ke gaya fungsional dengan misalnya, C #, Anda akan dengan cepat menemukan kebutuhan untuk tipe-tipe majemuk ini.
void/throw
dannull
tidak merasa benar dengan kode tersebut. Dan serikat pekerja yang didiskriminasi (DU) cocok dengan tagihan. Jadi, Anda mendapati diri Anda menginginkannya, seperti halnya banyak dari kita.Kabar baiknya adalah bahwa ada banyak perpustakaan di luar sana yang memodelkan DU dalam contoh C # (lihat perpustakaan Succinc <T> saya sendiri misalnya).
sumber
Jenis penjumlahan akan secara umum kurang bermanfaat dalam bahasa OO arus utama karena mereka memecahkan jenis masalah yang serupa dengan subtipe OO. Salah satu cara untuk melihat mereka adalah bahwa keduanya menangani subtyping tetapi OO adalah
open
yaitu seseorang dapat menambahkan subtipe sewenang-wenang ke tipe induk dan tipe penjumlahanclosed
yaitu menentukan menentukan dimuka apa subtipe yang valid.Sekarang, banyak bahasa OO menggabungkan subtyping dengan konsep-konsep lain seperti struct yang diwarisi, polimorfisme, pengetikan referensi dll untuk menjadikannya secara umum lebih bermanfaat. Konsekuensinya adalah bahwa mereka cenderung lebih banyak bekerja untuk mengatur (dengan kelas dan konstruktor dan yang lainnya) sehingga cenderung tidak digunakan untuk hal-hal seperti
Result
s danOption
s dan seterusnya sampai mengetik generik menjadi umum.Saya juga akan mengatakan bahwa fokus pada hubungan dunia nyata yang dipelajari kebanyakan orang ketika mereka memulai pemrograman OO misalnya Dog isa Animal, berarti Integer isa Result atau Error isa Result tampak agak asing. Padahal idenya sangat mirip.
Seperti mengapa bahasa fungsional mungkin lebih suka mengetik tertutup daripada mengetik terbuka, salah satu alasan yang mungkin adalah bahwa mereka cenderung lebih memilih pencocokan pola. Ini berguna untuk polimorfisme fungsi tetapi juga bekerja sangat baik dengan tipe tertutup karena kompiler dapat memeriksa secara statis bahwa pencocokan mencakup semua subtipe. Ini dapat membuat bahasa terasa lebih konsisten meskipun saya tidak percaya ada manfaat yang melekat (saya bisa salah).
sumber
sealed
berarti "hanya dapat diperpanjang dalam unit kompilasi yang sama", yang memungkinkan Anda untuk menutup set subclass pada waktu desain.Swift dengan senang hati menggunakan serikat diskriminatif, kecuali menyebut mereka "enum". Enum adalah salah satu dari lima kategori dasar objek di Swift, yang terdiri dari kelas, struct, enum, tuple, dan closure. Opsional Swift adalah enum yang merupakan serikat diskriminatif, dan mereka sangat penting untuk kode Swift apa pun.
Jadi premis bahwa "serikat diskriminatif terkait dengan pemrograman fungsional" salah.
sumber