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 a
yang 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 a
dan 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 Just
atau Nothing
, tidak ada kemungkinan (non-error) lainnya.
Karena Nothing
tidak memiliki tipe parameter, ketika digunakan sebagai konstruktor, ia menamai nilai konstan yang merupakan anggota tipe Maybe a
untuk semua tipe a
. Tetapi Just
konstruktor memiliki parameter tipe, yang berarti bahwa ketika digunakan sebagai konstruktor, ia bertindak seperti fungsi dari tipe a
ke 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 a
nilai 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 val
ke parameter yang diteruskan ke Just
konstruktor ketika nilai yang Anda cocokkan dibuat.
What Maybe Means
Mungkin Anda sudah terbiasa dengan cara kerjanya; sebenarnya tidak ada keajaiban untuk Maybe
nilai, itu hanya Haskell Algebraic Data Type (ADT) normal. Tapi itu digunakan cukup banyak karena secara efektif "mengangkat" atau memperluas tipe, seperti Integer
dari 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 Integer
yang 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 a
memiliki instance berguna.
Functor
menyediakan 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 fmap
untuk mengerjakan Maybe
nilai 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 Integer
nilai m_x
dan Int -> Int
fungsi f
, Anda dapat fmap f m_x
menerapkan fungsi tersebut f
secara langsung ke Maybe Integer
tanpa khawatir apakah fungsi tersebut benar-benar bernilai atau tidak. Faktanya, Anda dapat menerapkan seluruh rangkaian Integer -> Integer
fungsi yang diangkat ke Maybe Integer
nilai dan hanya perlu mengkhawatirkan pemeriksaan secara eksplisit untuk Nothing
sekali saat Anda selesai.
Mungkin sebagai Monad
Saya tidak yakin seberapa akrab Anda dengan konsep a Monad
yet, tetapi Anda setidaknya pernah menggunakan IO a
sebelumnya, dan tipe tanda tangan IO a
terlihat sangat mirip Maybe a
. Meskipun IO
spesial karena tidak mengekspos konstruktornya kepada Anda dan dengan demikian hanya dapat "dijalankan" oleh sistem runtime Haskell, ia juga merupakan Functor
tambahan untuk menjadi a Monad
. Faktanya, ada perasaan penting di mana a Monad
hanyalah jenis khusus Functor
dengan beberapa fitur tambahan, tetapi ini bukan tempat untuk membahasnya.
Bagaimanapun, Monad menyukai IO
tipe peta menjadi tipe baru yang merepresentasikan "komputasi yang menghasilkan nilai" dan Anda dapat mengangkat fungsi menjadi Monad
tipe melalui fmap
fungsi yang sangat mirip yang disebut liftM
yang mengubah fungsi reguler menjadi "komputasi yang menghasilkan nilai yang diperoleh dengan mengevaluasi fungsi."
Anda mungkin telah menebak (jika Anda telah membaca sejauh ini) itu Maybe
juga a Monad
. Ini mewakili "perhitungan yang bisa gagal mengembalikan nilai". Sama seperti fmap
contoh, ini memungkinkan Anda melakukan banyak komputasi tanpa harus memeriksa kesalahan secara eksplisit setelah setiap langkah. Dan pada kenyataannya, cara Monad
instance dibuat, penghitungan Maybe
nilai berhenti segera setelah a Nothing
ditemukan, 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 Maybe
tipe 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 Maybe
jenis dan konstruktornya sekarang, tetapi jika masih ada yang kurang jelas, beri tahu saya!
Maybe
mana bahasa lain akan digunakannull
ataunil
(dengan kata jahatNullPointerException
bersembunyi di setiap sudut). Sekarang bahasa lain mulai menggunakan konstruksi ini juga: Scala asOption
, dan bahkan Java 8 akan memilikiOptional
tipenya.