จริงๆแล้วมันเป็นเพียงตัวสร้างข้อมูลธรรมดาที่ถูกกำหนดไว้ในPreludeซึ่งเป็นไลบรารีมาตรฐานที่นำเข้าโดยอัตโนมัติในทุกโมดูล
สิ่งที่อาจจะเป็นโครงสร้าง
คำจำกัดความมีลักษณะดังนี้:
data Maybe a = Just a
| Nothing
ประกาศที่กำหนดประเภท, Maybe aซึ่งจะแปรตามตัวแปรประเภทซึ่งหมายความเพียงแค่ว่าคุณสามารถใช้มันด้วยวิธีใดในสถานที่ของaa
การสร้างและการทำลายล้าง
ประเภทนี้มีตัวสร้างสองตัวJust aและNothing. เมื่อประเภทมีตัวสร้างหลายตัวหมายความว่าค่าของประเภทจะต้องถูกสร้างขึ้นด้วยตัวสร้างที่เป็นไปได้เพียงตัวเดียว สำหรับประเภทนี้ค่าถูกสร้างขึ้นโดยผ่านJustหรือNothingไม่มีความเป็นไปได้อื่น ๆ (ไม่ใช่ข้อผิดพลาด)
เนื่องจากNothingไม่มีพารามิเตอร์ชนิดเมื่อใช้เป็นตัวสร้างชื่อมันมีค่าคงที่เป็นสมาชิกประเภททุกประเภทMaybe a aแต่ตัวJustสร้างมีพารามิเตอร์ชนิดซึ่งหมายความว่าเมื่อใช้เป็นตัวสร้างมันจะทำหน้าที่เหมือนฟังก์ชันจากชนิดaถึงMaybe aกล่าวคือมีประเภทa -> Maybe a
ดังนั้นตัวสร้างประเภทจึงสร้างมูลค่าของประเภทนั้น อีกด้านหนึ่งคือเมื่อคุณต้องการใช้ค่านั้นและนั่นคือจุดที่การจับคู่รูปแบบเข้ามาเล่น ซึ่งแตกต่างจากฟังก์ชันตัวสร้างสามารถใช้ในนิพจน์การผูกรูปแบบและนี่คือวิธีที่คุณสามารถวิเคราะห์กรณีของค่าที่เป็นของชนิดที่มีตัวสร้างมากกว่าหนึ่งตัว
ในการใช้Maybe aค่าในการจับคู่รูปแบบคุณต้องระบุรูปแบบสำหรับตัวสร้างแต่ละตัวดังนี้:
case maybeVal of
Nothing -> "There is nothing!"
Just val -> "There is a value, and it is " ++ (show val)
ในการแสดงออกที่กรณีที่รูปแบบครั้งแรกจะตรงกับถ้าค่าเป็นและที่สองจะตรงกับถ้าค่าที่ถูกสร้างขึ้นด้วยNothing Justหากอันที่สองตรงกันชื่อนี้จะผูกชื่อvalกับพารามิเตอร์ที่ส่งผ่านไปยังตัวJustสร้างเมื่อสร้างค่าที่คุณจับคู่ด้วย
สิ่งที่อาจหมายถึง
บางทีคุณอาจคุ้นเคยกับวิธีการทำงานนี้แล้ว ไม่มีความมหัศจรรย์ใด ๆ ต่อMaybeค่ามันเป็นเพียงประเภทข้อมูลพีชคณิตของ Haskell ปกติ (ADT) แต่มีการใช้ค่อนข้างน้อยเนื่องจาก "ยก" หรือขยายประเภทได้อย่างมีประสิทธิภาพเช่นIntegerจากตัวอย่างของคุณไปสู่บริบทใหม่ที่มีค่าพิเศษ ( Nothing) ซึ่งแสดงถึงการขาดคุณค่า! ระบบประเภทแล้วคุณจะต้องตรวจสอบว่าค่าพิเศษก่อนที่มันจะช่วยให้คุณได้รับที่Integerว่าอาจจะมี วิธีนี้ป้องกันข้อบกพร่องจำนวนมาก
หลายภาษาในปัจจุบันจัดการค่า "ไม่มีค่า" ประเภทนี้ผ่านการอ้างอิง NULL Tony Hoare นักวิทยาศาสตร์คอมพิวเตอร์ที่มีชื่อเสียง (เขาเป็นผู้คิดค้น Quicksort และเป็นผู้ชนะรางวัล Turing Award) เป็นเจ้าของสิ่งนี้ในฐานะ"ความผิดพลาดพันล้านดอลลาร์" ของเขา ประเภทบางทีไม่ใช่วิธีเดียวในการแก้ไขปัญหานี้ แต่ได้รับการพิสูจน์แล้วว่าเป็นวิธีที่มีประสิทธิภาพ
อาจจะเป็น Functor
ความคิดของการเปลี่ยนประเภทหนึ่งไปยังอีกที่หนึ่งเช่นว่าการดำเนินการกับชนิดเก่าสามารถยังถูกเปลี่ยนการทำงานในรูปแบบใหม่เป็นแนวคิดที่อยู่เบื้องหลังระดับประเภท Haskell เรียกว่าFunctorซึ่งMaybe aมีตัวอย่างการใช้งานของ
Functorจัดเตรียมวิธีการที่เรียกว่าfmapซึ่งแมปฟังก์ชันที่มีช่วงค่าจากประเภทพื้นฐาน (เช่นInteger) ไปยังฟังก์ชันที่มีช่วงค่าจากประเภทที่ยกขึ้น (เช่นMaybe Integer) ฟังก์ชันที่แปลงfmapเพื่อทำงานกับMaybeค่าจะทำงานดังนี้:
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
ดังนั้นหากคุณมีMaybe Integerค่าm_xและInt -> Intฟังก์ชันfคุณสามารถfmap f m_xนำฟังก์ชันไปใช้ได้fโดยตรงMaybe Integerโดยไม่ต้องกังวลว่าจะมีค่าจริงหรือไม่ ในความเป็นจริงคุณสามารถใช้ห่วงโซ่ของInteger -> Integerฟังก์ชันยกทั้งหมดกับMaybe Integerค่าและต้องกังวลเกี่ยวกับการตรวจสอบอย่างชัดเจนNothingเพียงครั้งเดียวเมื่อคุณทำเสร็จแล้ว
อาจจะเป็น Monad
ผมไม่แน่ใจว่าคุณจะคุ้นเคยกับแนวคิดของการที่Monadแต่คุณมีอย่างน้อยใช้IO aก่อนและประเภทลายเซ็นรูปลักษณ์ที่น่าทึ่งคล้ายกับIO a Maybe aแม้ว่าจะIOมีความพิเศษตรงที่จะไม่เปิดเผยตัวสร้างให้คุณและสามารถ "รัน" ได้โดยระบบรันไทม์ของ Haskell เท่านั้น แต่ก็ยังเป็นFunctorไฟล์Monad. ในความเป็นจริงมีความรู้สึกที่สำคัญซึ่ง a Monadเป็นเพียงลักษณะพิเศษที่Functorมีคุณสมบัติพิเศษบางอย่าง แต่นี่ไม่ใช่สถานที่ที่จะเข้าไปในนั้น
อย่างไรก็ตาม Monads ชอบIOประเภทแผนที่เป็นประเภทใหม่ที่แสดงถึง "การคำนวณที่ทำให้เกิดค่า" และคุณสามารถยกฟังก์ชันออกเป็นMonadประเภทได้ผ่านfmapฟังก์ชันที่เหมือนมากซึ่งเรียก liftMว่าฟังก์ชันปกติให้เป็น "การคำนวณที่ให้ผลลัพธ์เป็นค่าที่ได้จากการประเมินค่า ฟังก์ชั่น."
คุณอาจเดาได้ (ถ้าคุณอ่านมาจนถึงตอนนี้) นั่นMaybeก็คือไฟล์Monad. ซึ่งแสดงถึง "การคำนวณที่ไม่สามารถคืนค่าได้" เช่นเดียวกับfmapตัวอย่างนี้ช่วยให้คุณสามารถคำนวณได้ทั้งหมดโดยไม่ต้องตรวจสอบข้อผิดพลาดอย่างชัดเจนหลังจากแต่ละขั้นตอน และในความเป็นจริงวิธีการสร้างMonadอินสแตนซ์การคำนวณเกี่ยวกับMaybeค่าจะหยุดลงทันทีที่Nothingพบa ดังนั้นจึงเหมือนกับการยกเลิกทันทีหรือผลตอบแทนที่ไร้ค่าในระหว่างการคำนวณ
คุณอาจจะเขียนได้
อย่างที่ฉันได้กล่าวไปก่อนหน้านี้ไม่มีอะไรที่อยู่ในMaybeประเภทที่รวมเข้ากับไวยากรณ์ของภาษาหรือระบบรันไทม์ หาก Haskell ไม่ได้จัดเตรียมไว้เป็นค่าเริ่มต้นคุณสามารถใช้ฟังก์ชันทั้งหมดได้ด้วยตัวคุณเอง! ในความเป็นจริงคุณสามารถเขียนซ้ำได้ด้วยตัวเองโดยใช้ชื่อที่แตกต่างกันและได้รับฟังก์ชันการทำงานเหมือนกัน
หวังว่าคุณจะเข้าใจMaybeประเภทและตัวสร้างในตอนนี้ แต่หากยังมีอะไรไม่ชัดเจนโปรดแจ้งให้เราทราบ!
Maybeที่ที่ภาษาอื่น ๆ จะใช้nullหรือnil(มีสิ่งที่น่ารังเกียจNullPointerExceptionแฝงตัวอยู่ทุกมุม) ตอนนี้ภาษาอื่น ๆ ก็เริ่มใช้โครงสร้างนี้เช่นกัน: Scala asOptionและแม้แต่ Java 8 ก็มีOptionalประเภท