Ini sebenarnya hanya konstruktor data normal yang kebetulan didefinisikan dalam Prelude , yang merupakan pustaka standar yang diimpor secara otomatis ke dalam setiap modul.
Apa Maybe itu, Secara Struktural
Definisi tersebut terlihat seperti ini:
data Maybe a = Just a
| Nothing
Deklarasi itu mendefinisikan sebuah tipe, Maybe ayang diparameterisasi oleh variabel tipe a, yang berarti Anda dapat menggunakannya dengan tipe apa pun sebagai pengganti a.
Membangun dan Menghancurkan
Tipe ini memiliki dua konstruktor, Just adan Nothing. Ketika suatu tipe memiliki banyak konstruktor, itu berarti bahwa nilai tipe harus dibangun hanya dengan salah satu konstruktor yang memungkinkan. Untuk tipe ini, nilai dibangun melalui Justatau Nothing, tidak ada kemungkinan (non-error) lainnya.
Karena Nothingtidak memiliki tipe parameter, ketika digunakan sebagai konstruktor, ia menamai nilai konstan yang merupakan anggota tipe Maybe auntuk semua tipe a. Tetapi Justkonstruktor memiliki parameter tipe, yang berarti bahwa ketika digunakan sebagai konstruktor, ia bertindak seperti fungsi dari tipe ake Maybe a, yaitu memiliki tipea -> Maybe a
Jadi, konstruktor tipe membangun nilai tipe itu; sisi lain adalah ketika Anda ingin menggunakan nilai itu, dan di situlah pencocokan pola berperan. Tidak seperti fungsi, konstruktor dapat digunakan dalam ekspresi pengikatan pola, dan ini adalah cara di mana Anda dapat melakukan analisis kasus nilai yang termasuk dalam tipe dengan lebih dari satu konstruktor.
Untuk menggunakan Maybe anilai dalam pencocokan pola, Anda perlu memberikan pola untuk setiap konstruktor, seperti:
case maybeVal of
Nothing -> "There is nothing!"
Just val -> "There is a value, and it is " ++ (show val)
Dalam ekspresi kasus tersebut, pola pertama akan cocok jika nilainya adalah Nothing, dan pola kedua akan cocok jika nilai itu dibuat Just. Jika yang kedua cocok, itu juga mengikat nama valke parameter yang diteruskan ke Justkonstruktor ketika nilai yang Anda cocokkan dibuat.
What Maybe Means
Mungkin Anda sudah terbiasa dengan cara kerjanya; sebenarnya tidak ada keajaiban untuk Maybenilai, itu hanya Haskell Algebraic Data Type (ADT) normal. Tapi itu digunakan cukup banyak karena secara efektif "mengangkat" atau memperluas tipe, seperti Integerdari contoh Anda, ke dalam konteks baru di mana ia memiliki nilai ekstra ( Nothing) yang merepresentasikan kurangnya nilai! Sistem tipe kemudian mengharuskan Anda memeriksa nilai ekstra itu sebelum memungkinkan Anda mendapatkan nilai Integeryang mungkin ada di sana. Ini mencegah sejumlah besar bug.
Banyak bahasa saat ini menangani nilai "tanpa nilai" semacam ini melalui referensi NULL. Tony Hoare, seorang ilmuwan komputer terkemuka (ia menemukan Quicksort dan merupakan pemenang Turing Award), menganggap ini sebagai "kesalahan miliaran dolar" . Jenis Mungkin bukan satu-satunya cara untuk memperbaikinya, tetapi telah terbukti menjadi cara yang efektif untuk melakukannya.
Mungkin sebagai Functor
Ide untuk mengubah satu tipe ke tipe lain sehingga operasi pada tipe lama juga bisa diubah untuk bekerja pada tipe baru adalah konsep di balik kelas tipe Haskell yang dipanggil Functor, yang Maybe amemiliki instance berguna.
Functormenyediakan metode yang dipanggil fmap, yang memetakan fungsi yang berkisar pada nilai dari tipe dasar (seperti Integer) ke fungsi yang berkisar pada nilai dari tipe yang diangkat (seperti Maybe Integer). Sebuah fungsi yang diubah dengan fmapuntuk mengerjakan Maybenilai bekerja seperti ini:
case maybeVal of
Nothing -> Nothing -- there is nothing, so just return Nothing
Just val -> Just (f val) -- there is a value, so apply the function to it
Jadi jika Anda memiliki Maybe Integernilai m_xdan Int -> Intfungsi f, Anda dapat fmap f m_xmenerapkan fungsi tersebut fsecara langsung ke Maybe Integertanpa khawatir apakah fungsi tersebut benar-benar bernilai atau tidak. Faktanya, Anda dapat menerapkan seluruh rangkaian Integer -> Integerfungsi yang diangkat ke Maybe Integernilai dan hanya perlu mengkhawatirkan pemeriksaan secara eksplisit untuk Nothingsekali saat Anda selesai.
Mungkin sebagai Monad
Saya tidak yakin seberapa akrab Anda dengan konsep a Monadyet, tetapi Anda setidaknya pernah menggunakan IO asebelumnya, dan tipe tanda tangan IO aterlihat sangat mirip Maybe a. Meskipun IOspesial karena tidak mengekspos konstruktornya kepada Anda dan dengan demikian hanya dapat "dijalankan" oleh sistem runtime Haskell, ia juga merupakan Functortambahan untuk menjadi a Monad. Faktanya, ada perasaan penting di mana a Monadhanyalah jenis khusus Functordengan beberapa fitur tambahan, tetapi ini bukan tempat untuk membahasnya.
Bagaimanapun, Monad menyukai IOtipe peta menjadi tipe baru yang merepresentasikan "komputasi yang menghasilkan nilai" dan Anda dapat mengangkat fungsi menjadi Monadtipe melalui fmapfungsi yang sangat mirip yang disebut liftMyang mengubah fungsi reguler menjadi "komputasi yang menghasilkan nilai yang diperoleh dengan mengevaluasi fungsi."
Anda mungkin telah menebak (jika Anda telah membaca sejauh ini) itu Maybejuga a Monad. Ini mewakili "perhitungan yang bisa gagal mengembalikan nilai". Sama seperti fmapcontoh, ini memungkinkan Anda melakukan banyak komputasi tanpa harus memeriksa kesalahan secara eksplisit setelah setiap langkah. Dan pada kenyataannya, cara Monadinstance dibuat, penghitungan Maybenilai berhenti segera setelah a Nothingditemukan, jadi ini seperti pembatalan langsung atau pengembalian tak berharga di tengah penghitungan.
Anda Mungkin Bisa Menulis
Seperti yang saya katakan sebelumnya, tidak ada yang melekat pada Maybetipe yang dimasukkan ke dalam sintaks bahasa atau sistem runtime. Jika Haskell tidak menyediakannya secara default, Anda dapat menyediakan semua fungsinya sendiri! Nyatanya, Anda tetap bisa menulisnya sendiri, dengan nama berbeda, dan mendapatkan fungsi yang sama.
Semoga Anda memahami Maybejenis dan konstruktornya sekarang, tetapi jika masih ada yang kurang jelas, beri tahu saya!
Maybemana bahasa lain akan digunakannullataunil(dengan kata jahatNullPointerExceptionbersembunyi di setiap sudut). Sekarang bahasa lain mulai menggunakan konstruksi ini juga: Scala asOption, dan bahkan Java 8 akan memilikiOptionaltipenya.