ในการdataประกาศตัวสร้างประเภทคือสิ่งที่อยู่ทางซ้ายมือของเครื่องหมายเท่ากับ ตัวสร้างข้อมูลคือสิ่งที่อยู่ทางขวามือของเครื่องหมายเท่ากับ คุณใช้ตัวสร้างประเภทที่คาดว่าจะมีประเภทและคุณใช้ตัวสร้างข้อมูลที่คาดว่าจะมีค่า
ตัวสร้างข้อมูล
เพื่อให้ง่ายขึ้นเราสามารถเริ่มต้นด้วยตัวอย่างของประเภทที่แสดงถึงสี
data Colour = Red | Green | Blue
ที่นี่เรามีตัวสร้างข้อมูลสามตัว Colourเป็นชนิดและเป็นตัวสร้างที่มีค่าของชนิดGreen ColourในทำนองเดียวกันRedและมีทั้งการก่อสร้างว่าค่าสร้างประเภทBlue Colourเราคงนึกภาพออกได้!
data Colour = RGB Int Int Int
เรายังคงมีเพียงประเภทColourแต่RGBไม่ใช่ค่า - เป็นฟังก์ชันที่ใช้สาม Ints และส่งคืนค่า! RGBมีประเภท
RGB :: Int -> Int -> Int -> Colour
RGBเป็นตัวสร้างข้อมูลที่เป็นฟังก์ชันที่รับค่าบางค่าเป็นอาร์กิวเมนต์จากนั้นใช้ค่าเหล่านั้นเพื่อสร้างค่าใหม่ หากคุณได้ทำการเขียนโปรแกรมเชิงวัตถุใด ๆ คุณควรตระหนักถึงสิ่งนี้ ใน OOP ตัวสร้างยังรับค่าบางค่าเป็นอาร์กิวเมนต์และส่งคืนค่าใหม่!
ในกรณีนี้ถ้าเราใช้RGBกับสามค่าเราจะได้ค่าสี!
Prelude> RGB 12 92 27
#0c5c1b
เราได้สร้างค่าของประเภทColourโดยใช้ตัวสร้างข้อมูล ตัวสร้างข้อมูลทั้งมีค่าเช่นตัวแปรจะหรือต้องใช้ค่าอื่น ๆ เป็นอาร์กิวเมนต์และสร้างใหม่ค่า หากคุณเคยเขียนโปรแกรมมาก่อนแนวคิดนี้ไม่น่าจะแปลกสำหรับคุณมากนัก
ช่วงระยะหยุดพัก
หากคุณต้องการสร้างต้นไม้ไบนารีเพื่อเก็บStrings คุณสามารถจินตนาการว่าจะทำสิ่งต่างๆเช่น
data SBTree = Leaf String
| Branch String SBTree SBTree
สิ่งที่เราเห็นนี้คือประเภทSBTreeที่มีตัวสร้างข้อมูลสองตัว กล่าวอีกนัยหนึ่งมีสองฟังก์ชัน (คือLeafและBranch) ที่จะสร้างค่าของSBTreeประเภท หากคุณไม่คุ้นเคยกับการทำงานของต้นไม้ไบนารีเพียงแค่เข้าไปที่นั่น คุณไม่จำเป็นต้องรู้ว่าต้นไม้ไบนารีทำงานอย่างไรเพียงแต่ว่าต้นนี้เก็บStringไว้ในทางใดทางหนึ่ง
นอกจากนี้เรายังเห็นว่าตัวสร้างข้อมูลทั้งสองมีStringอาร์กิวเมนต์ - นี่คือ String ที่พวกเขาจะเก็บไว้ในแผนภูมิ
แต่! จะเป็นอย่างไรหากเราต้องการจัดเก็บBoolด้วยเราจะต้องสร้างต้นไม้ไบนารีใหม่ อาจมีลักษณะดังนี้:
data BBTree = Leaf Bool
| Branch Bool BBTree BBTree
ประเภทตัวสร้าง
ทั้งสองSBTreeและBBTreeเป็นตัวสร้างประเภท แต่มีปัญหาที่ชัดเจน คุณเห็นไหมว่ามันคล้ายกันแค่ไหน? นั่นเป็นสัญญาณว่าคุณต้องการพารามิเตอร์ที่ไหนสักแห่ง
ดังนั้นเราสามารถทำได้:
data BTree a = Leaf a
| Branch a (BTree a) (BTree a)
ตอนนี้เราแนะนำตัวแปร type aเป็นพารามิเตอร์ให้กับ type constructor ในคำประกาศนี้BTreeได้กลายเป็นฟังก์ชัน มันต้องใช้เวลาประเภทเป็นอาร์กิวเมนต์และมันส่งกลับใหม่ประเภท
มันเป็นสิ่งสำคัญที่นี่เพื่อพิจารณาความแตกต่างระหว่างที่ประเภทคอนกรีต (ตัวอย่าง ได้แก่Int, [Char]และMaybe Bool) ซึ่งเป็นชนิดที่สามารถกำหนดให้มีค่าในโปรแกรมของคุณและฟังก์ชั่นประเภทคอนสตรัคที่คุณจำเป็นต้องให้อาหารชนิดเพื่อให้สามารถที่จะ กำหนดให้กับค่า ค่าไม่สามารถเป็นประเภท "list" ได้เนื่องจากต้องเป็น "list of something " ในจิตวิญญาณเดียวกันค่าไม่สามารถเป็นประเภท "ต้นไม้ไบนารี" ได้เพราะจำเป็นต้องเป็น "ต้นไม้ไบนารีที่เก็บบางสิ่ง "
ถ้าเราส่งผ่านกล่าวว่าBoolเป็นอาร์กิวเมนต์BTreeมันจะส่งกลับประเภทBTree Boolซึ่งเป็นต้นไม้ไบนารีที่เก็บBools แทนที่ตัวแปร type ทุกครั้งaด้วย type Boolแล้วคุณจะเห็นเองว่ามันจริงแค่ไหน
หากคุณต้องการคุณสามารถดูBTreeเป็นฟังก์ชันด้วยชนิด
BTree :: * -> *
ชนิดค่อนข้างเหมือนประเภท - *หมายถึงประเภทคอนกรีตดังนั้นเราจึงกล่าวว่าBTreeมาจากประเภทคอนกรีตไปจนถึงประเภทคอนกรีต
ห่อ
ย้อนกลับมาที่นี่สักครู่และสังเกตความคล้ายคลึงกัน
ตัวสร้างข้อมูลที่มีพารามิเตอร์นั้นยอดเยี่ยมหากเราต้องการให้ค่าของเราเปลี่ยนแปลงเล็กน้อย - เราใส่ความแปรผันเหล่านั้นในพารามิเตอร์และปล่อยให้คนที่สร้างค่าเป็นผู้ตัดสินใจว่าพวกเขาจะใส่อาร์กิวเมนต์ใดในแง่เดียวกันการพิมพ์ตัวสร้างที่มีพารามิเตอร์ก็เจ๋ง หากเราต้องการความแตกต่างเล็กน้อยในประเภทของเรา! เราใส่รูปแบบเหล่านั้นเป็นพารามิเตอร์และปล่อยให้คนที่สร้างประเภทตัดสินใจว่าพวกเขาจะใส่อาร์กิวเมนต์อะไร
กรณีศึกษา
ในฐานะที่เป็นบ้านที่นี่เราสามารถพิจารณาMaybe aประเภทได้ คำจำกัดความของมันคือ
data Maybe a = Nothing
| Just a
นี่Maybeคือตัวสร้างชนิดที่ส่งคืนประเภทคอนกรีต Justเป็นตัวสร้างข้อมูลที่ส่งคืนค่า Nothingเป็นตัวสร้างข้อมูลที่มีค่า ถ้าเราดูประเภทของJustเราจะเห็นว่า
Just :: a -> Maybe a
ในคำอื่น ๆJustใช้ค่าของชนิดและผลตอบแทนค่าของชนิดa Maybe aถ้าเราดูประเภทของMaybeเราจะเห็นว่า
Maybe :: * -> *
กล่าวอีกนัยหนึ่งคือMaybeรับประเภทคอนกรีตและส่งคืนประเภทคอนกรีต
อีกครั้ง! ความแตกต่างระหว่างประเภทคอนกรีตและฟังก์ชันตัวสร้างประเภท คุณไม่สามารถสร้างรายการMaybes ได้หากคุณพยายามดำเนินการ
[] :: [Maybe]
คุณจะได้รับข้อผิดพลาด แต่คุณสามารถสร้างรายการหรือMaybe Int Maybe aนั่นเป็นเพราะMaybeเป็นฟังก์ชันตัวสร้างชนิด แต่รายการต้องมีค่าของประเภทคอนกรีต Maybe IntและMaybe aเป็นประเภทคอนกรีต (หรือถ้าคุณต้องการให้เรียกใช้ฟังก์ชันตัวสร้างที่ส่งคืนชนิดคอนกรีต)
Carเป็นทั้งตัวสร้างประเภท (ทางด้านซ้ายของ=) และตัวสร้างข้อมูล (ทางด้านขวา) ในตัวอย่างแรกตัวCarสร้างประเภทจะไม่มีอาร์กิวเมนต์ในตัวอย่างที่สองจะใช้เวลาสาม ในทั้งสองตัวอย่างตัวCarสร้างข้อมูลรับอาร์กิวเมนต์สามตัว (แต่ประเภทของอาร์กิวเมนต์เหล่านั้นอยู่ในกรณีเดียวคงที่และในพารามิเตอร์อื่น ๆ )