Dalam data
deklarasi, 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. Colour
adalah tipe, dan Green
merupakan konstruktor yang berisi nilai tipe Colour
. Demikian pula, Red
dan Blue
keduanya merupakan konstruktor yang membangun nilai tipe Colour
. Kita bisa membayangkan membumbuinya!
data Colour = RGB Int Int Int
Kami masih memiliki tipe Colour
, tetapi RGB
bukan nilai - ini adalah fungsi yang mengambil tiga Ints dan mengembalikan nilai! RGB
memiliki tipe
RGB :: Int -> Int -> Int -> Colour
RGB
adalah 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 RGB
ke tiga nilai, kita mendapatkan nilai warna!
Prelude> RGB 12 92 27
#0c5c1b
Kami telah membangun nilai tipe Colour
dengan 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 SBTree
yang berisi dua konstruktor data. Dengan kata lain, ada dua fungsi (yaitu Leaf
dan Branch
) yang akan membentuk nilai dari SBTree
tipe 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 String
dengan cara tertentu.
Kita juga melihat bahwa kedua konstruktor data mengambil String
argumen - 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 SBTree
dan BBTree
merupakan 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, BTree
telah 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, Bool
sebagai argumen ke BTree
, ia mengembalikan tipe BTree Bool
, yang merupakan pohon biner yang menyimpan Bool
s. Gantikan setiap kemunculan variabel tipe a
dengan tipe Bool
, dan Anda dapat melihat sendiri bagaimana itu benar.
Jika mau, Anda dapat melihat BTree
sebagai fungsi dengan jenis
BTree :: * -> *
Jenis agak mirip jenis - yang *
menunjukkan jenis beton, jadi kami katakan BTree
adalah 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 a
jenisnya. Definisinya adalah
data Maybe a = Nothing
| Just a
Di sini, Maybe
adalah tipe konstruktor yang mengembalikan tipe beton. Just
adalah konstruktor data yang mengembalikan nilai. Nothing
adalah konstruktor data yang berisi nilai. Jika kita melihat jenisnya Just
, kita melihatnya
Just :: a -> Maybe a
Dengan kata lain, Just
mengambil nilai tipe a
dan mengembalikan nilai tipe Maybe a
. Jika kita melihat jenisnya Maybe
, kita melihatnya
Maybe :: * -> *
Dengan kata lain, Maybe
mengambil tipe konkret dan mengembalikan tipe konkret.
Sekali lagi! Perbedaan antara tipe beton dan fungsi tipe konstruktor. Anda tidak dapat membuat daftar Maybe
s - jika Anda mencoba untuk mengeksekusi
[] :: [Maybe]
Anda akan mendapatkan kesalahan. Namun Anda dapat membuat daftar Maybe Int
, atau Maybe a
. Itu karena Maybe
merupakan fungsi konstruktor tipe, tetapi daftar harus berisi nilai dari tipe konkret. Maybe Int
dan Maybe a
merupakan tipe konkret (atau jika Anda ingin, panggilan ke fungsi konstruktor tipe yang mengembalikan tipe konkret.)
Car
merupakan konstruktor tipe (di sisi kiri=
) dan konstruktor data (di sisi kanan). Pada contoh pertama,Car
konstruktor tipe tidak membutuhkan argumen, pada contoh kedua dibutuhkan tiga argumen. Dalam kedua contoh tersebut,Car
konstruktor data mengambil tiga argumen (tetapi tipe argumen tersebut dalam satu kasus diperbaiki dan dalam kasus lain diparameterisasi).