ใน GHCi:
Prelude> error (error "")
*** Exception:
Prelude> (error . error) ""
*** Exception: *** Exception:
เหตุใดข้อแรกจึงไม่เป็นข้อยกเว้นที่ซ้อนกัน
ใน GHCi:
Prelude> error (error "")
*** Exception:
Prelude> (error . error) ""
*** Exception: *** Exception:
เหตุใดข้อแรกจึงไม่เป็นข้อยกเว้นที่ซ้อนกัน
error
เป็นกลไกพิเศษและไม่ใช่กลไกยกเว้น สำหรับข้อยกเว้นที่จับได้จริงโปรดดูError
monad
(\f g x -> f (g x)) error error ""
ทำงานแตกต่างจาก(.) error error ""
แม้ว่าฟังก์ชันนั้นจะเทียบเท่ากับ(.)
. อาจเกี่ยวข้องกับแฟล็กการปรับให้เหมาะสมที่ Prelude ถูกคอมไพล์ด้วย
iterate error "" !! n
fix error
error = error
และตั้งโปรแกรมตามนั้น
คำตอบ:
คำตอบคือนี่เป็นความหมายของข้อยกเว้นที่ไม่ชัดเจน (ค่อนข้างน่าแปลกใจ)
เมื่อรหัสบริสุทธิ์สามารถแสดงเพื่อประเมินเป็นชุดของค่าพิเศษ (เช่นค่าของ error
หรือundefined
และอย่างชัดเจนไม่ใช่ชนิดของข้อยกเว้นที่สร้างขึ้นใน IO ) ภาษาจะอนุญาตให้ส่งคืนค่าใด ๆ ของชุดนั้น ค่าพิเศษใน Haskell มีลักษณะคล้ายกับNaN
รหัสทศนิยมมากกว่าข้อยกเว้นตามโฟลว์การควบคุมในภาษาที่จำเป็น
gotcha เป็นครั้งคราวสำหรับแม้แต่ Haskellers ขั้นสูงก็เป็นกรณีเช่น:
case x of
1 -> error "One"
_ -> error "Not one"
เนื่องจากโค้ดประเมินเป็นชุดของข้อยกเว้น GHC จึงมีอิสระที่จะเลือกอย่างใดอย่างหนึ่ง เมื่อเปิดการเพิ่มประสิทธิภาพคุณอาจพบว่าสิ่งนี้ประเมินเป็น "ไม่ใช่อย่างเดียว" เสมอ
ทำไมเราถึงทำเช่นนี้? เพราะไม่เช่นนั้นเราจะ จำกัด ลำดับการประเมินของภาษามากเกินไปเช่นเราจะต้องแก้ไขผลลัพธ์ที่กำหนดไว้สำหรับ:
f (error "a") (error "b")
โดยตัวอย่างเช่นกำหนดให้มีการประเมินจากซ้ายไปขวาหากมีค่าความผิดพลาด ฮาสเคลลี่มาก!
เนื่องจากเราไม่ต้องการทำให้การเพิ่มประสิทธิภาพที่สามารถทำได้ในโค้ดของเราทำให้เสียประโยชน์เพียงเพื่อสนับสนุน error
วิธีแก้ปัญหาคือการระบุว่าผลลัพธ์เป็นทางเลือกที่ไม่ได้กำหนดจากชุดค่าพิเศษ: ข้อยกเว้นที่ไม่ชัดเจน! ในทางหนึ่งข้อยกเว้นทั้งหมดจะถูกส่งกลับและหนึ่งจะถูกเลือก
โดยปกติคุณไม่สนใจข้อยกเว้นคือข้อยกเว้นเว้นแต่คุณจะสนใจสตริงภายในข้อยกเว้นซึ่งในกรณีนี้การใช้error
เพื่อดีบักจะทำให้เกิดความสับสนอย่างมาก
การอ้างอิง: ความหมายสำหรับข้อยกเว้นที่ไม่ชัดเจน Simon Peyton Jones, Alastair Reid, Tony Hoare, Simon Marlow, Fergus Henderson Proc Programming Languages Design and Implementation (PLDI'99), Atlanta ( PDF )
throw
) และคุณสามารถกำหนดข้อยกเว้นthrowIO
ได้
case error "banana" of (x:xs) -> error "bonobo"
สามารถให้คุณ* Exception: bonobo
.