Dalam datadeklarasi, konstruktor tipe adalah benda di sisi kiri dari tanda sama dengan. The Data konstruktor (s) adalah hal-hal di sisi kanan tanda sama. Anda menggunakan konstruktor tipe di mana sebuah tipe diharapkan, dan Anda menggunakan konstruktor data di mana sebuah nilai diharapkan.
Konstruktor data
Untuk menyederhanakannya, kita bisa mulai dengan contoh tipe yang mewakili warna.
data Colour = Red | Green | Blue
Di sini, kami memiliki tiga konstruktor data. Colouradalah tipe, dan Greenmerupakan konstruktor yang berisi nilai tipe Colour. Demikian pula, Reddan Bluekeduanya merupakan konstruktor yang membangun nilai tipe Colour. Kita bisa membayangkan membumbuinya!
data Colour = RGB Int Int Int
Kami masih memiliki tipe Colour, tetapi RGBbukan nilai - ini adalah fungsi yang mengambil tiga Ints dan mengembalikan nilai! RGBmemiliki tipe
RGB :: Int -> Int -> Int -> Colour
RGBadalah konstruktor data yang merupakan fungsi yang mengambil beberapa nilai sebagai argumennya, dan kemudian menggunakannya untuk membuat nilai baru. Jika Anda pernah melakukan pemrograman berorientasi objek, Anda harus mengenali ini. Dalam OOP, konstruktor juga mengambil beberapa nilai sebagai argumen dan mengembalikan nilai baru!
Dalam hal ini, jika kita menerapkan RGBke tiga nilai, kita mendapatkan nilai warna!
Prelude> RGB 12 92 27
#0c5c1b
Kami telah membangun nilai tipe Colourdengan menerapkan konstruktor data. Konstruktor data berisi nilai seperti variabel, atau menggunakan nilai lain sebagai argumennya dan membuat nilai baru . Jika Anda telah melakukan pemrograman sebelumnya, konsep ini seharusnya tidak terlalu aneh bagi Anda.
Istirahat
Jika Anda ingin membangun pohon biner untuk menyimpan String, Anda dapat membayangkan melakukan sesuatu seperti
data SBTree = Leaf String
| Branch String SBTree SBTree
Apa yang kita lihat di sini adalah tipe SBTreeyang berisi dua konstruktor data. Dengan kata lain, ada dua fungsi (yaitu Leafdan Branch) yang akan membentuk nilai dari SBTreetipe tersebut. Jika Anda tidak terbiasa dengan cara kerja pohon biner, bertahanlah di sana. Anda sebenarnya tidak perlu tahu cara kerja pohon biner, hanya yang satu ini menyimpan Stringdengan cara tertentu.
Kita juga melihat bahwa kedua konstruktor data mengambil Stringargumen - ini adalah String yang akan mereka simpan di pohon.
Tapi! Bagaimana jika kita juga ingin bisa menyimpan Bool, kita harus membuat pohon biner baru. Ini bisa terlihat seperti ini:
data BBTree = Leaf Bool
| Branch Bool BBTree BBTree
Ketik konstruktor
Keduanya SBTreedan BBTreemerupakan konstruktor tipe. Tapi ada masalah yang mencolok. Apakah Anda melihat betapa miripnya mereka? Itu pertanda bahwa Anda benar-benar menginginkan parameter di suatu tempat.
Jadi kita bisa melakukan ini:
data BTree a = Leaf a
| Branch a (BTree a) (BTree a)
Sekarang kami memperkenalkan variabel tipe a sebagai parameter ke tipe konstruktor. Dalam deklarasi ini, BTreetelah menjadi fungsi. Ini mengambil tipe sebagai argumennya dan mengembalikan tipe baru .
Penting di sini untuk mempertimbangkan perbedaan antara tipe konkret (contoh termasuk Int, [Char]dan Maybe Bool) yang merupakan tipe yang dapat ditetapkan ke nilai dalam program Anda, dan fungsi konstruktor tipe yang Anda perlukan untuk memberi makan tipe agar bisa menjadi ditetapkan ke suatu nilai. Sebuah nilai tidak pernah bisa berjenis "daftar", karena ia harus berupa "daftar sesuatu ". Dalam semangat yang sama, suatu nilai tidak pernah bisa berjenis "pohon biner", karena ia harus berupa "pohon biner yang menyimpan sesuatu ".
Jika kita meneruskan, katakanlah, Boolsebagai argumen ke BTree, ia mengembalikan tipe BTree Bool, yang merupakan pohon biner yang menyimpan Bools. Gantikan setiap kemunculan variabel tipe adengan tipe Bool, dan Anda dapat melihat sendiri bagaimana itu benar.
Jika mau, Anda dapat melihat BTreesebagai fungsi dengan jenis
BTree :: * -> *
Jenis agak mirip jenis - yang *menunjukkan jenis beton, jadi kami katakan BTreeadalah dari jenis beton ke jenis beton.
Membungkus
Mundur sejenak ke sini dan catat persamaannya.
Sebuah konstruktor Data adalah "fungsi" yang mengambil 0 atau lebih nilai-nilai dan memberikan Anda kembali nilai baru.
Sebuah tipe konstruktor adalah "fungsi" yang mengambil 0 atau lebih jenis dan memberikan Anda kembali jenis baru.
Konstruktor data dengan parameter itu keren jika kita ingin sedikit variasi dalam nilai kita - kita menempatkan variasi dalam parameter dan membiarkan orang yang membuat nilai memutuskan argumen apa yang akan mereka masukkan. Dalam pengertian yang sama, jenis konstruktor dengan parameter itu keren jika kita ingin sedikit variasi dalam tipe kita! Kami menempatkan variasi tersebut sebagai parameter dan membiarkan orang yang membuat jenis memutuskan argumen apa yang akan mereka masukkan.
Studi kasus
Sebagai peregangan rumah di sini, kita dapat mempertimbangkan Maybe ajenisnya. Definisinya adalah
data Maybe a = Nothing
| Just a
Di sini, Maybeadalah tipe konstruktor yang mengembalikan tipe beton. Justadalah konstruktor data yang mengembalikan nilai. Nothingadalah konstruktor data yang berisi nilai. Jika kita melihat jenisnya Just, kita melihatnya
Just :: a -> Maybe a
Dengan kata lain, Justmengambil nilai tipe adan mengembalikan nilai tipe Maybe a. Jika kita melihat jenisnya Maybe, kita melihatnya
Maybe :: * -> *
Dengan kata lain, Maybemengambil tipe konkret dan mengembalikan tipe konkret.
Sekali lagi! Perbedaan antara tipe beton dan fungsi tipe konstruktor. Anda tidak dapat membuat daftar Maybes - jika Anda mencoba untuk mengeksekusi
[] :: [Maybe]
Anda akan mendapatkan kesalahan. Namun Anda dapat membuat daftar Maybe Int, atau Maybe a. Itu karena Maybemerupakan fungsi konstruktor tipe, tetapi daftar harus berisi nilai dari tipe konkret. Maybe Intdan Maybe amerupakan tipe konkret (atau jika Anda ingin, panggilan ke fungsi konstruktor tipe yang mengembalikan tipe konkret.)
Carmerupakan konstruktor tipe (di sisi kiri=) dan konstruktor data (di sisi kanan). Pada contoh pertama,Carkonstruktor tipe tidak membutuhkan argumen, pada contoh kedua dibutuhkan tiga argumen. Dalam kedua contoh tersebut,Carkonstruktor data mengambil tiga argumen (tetapi tipe argumen tersebut dalam satu kasus diperbaiki dan dalam kasus lain diparameterisasi).