อาจจะเป็นข้อยกเว้น Monad


34

ฉันสงสัยว่าอะไรคือข้อดีของMaybe monad ที่มีข้อยกเว้น? ดูเหมือนว่าMaybeเป็นวิธีการทางtry..catchไวยากรณ์ที่ชัดเจน (และค่อนข้างใช้พื้นที่มาก)

อัปเดตโปรดทราบว่าฉันตั้งใจจะไม่พูดถึง Haskell

คำตอบ:


56

การใช้Maybe(หรือลูกพี่ลูกน้องของมันEitherซึ่งใช้งานได้ในลักษณะเดียวกัน แต่ให้คุณคืนค่าโดยพลการแทนNothing) ทำหน้าที่แตกต่างกันเล็กน้อยกว่าข้อยกเว้น ในแง่ของจาวาก็เหมือนกับมีข้อยกเว้นตรวจสอบมากกว่าข้อยกเว้นรันไทม์ มันแสดงถึงสิ่งที่คาดหวังซึ่งคุณต้องจัดการแทนที่จะเป็นข้อผิดพลาดที่คุณไม่คาดคิด

ฟังก์ชันที่ต้องการindexOfคืนMaybeค่าเพราะคุณคาดหวังความเป็นไปได้ที่ไอเท็มนั้นจะไม่อยู่ในรายการ มันเหมือนกับกลับมาnullจากฟังก์ชั่นยกเว้นในวิธีที่ปลอดภัยประเภทที่บังคับให้คุณจัดการกับnullกรณีและปัญหา ทำงานในลักษณะเดียวกันยกเว้นว่าคุณสามารถส่งกลับข้อมูลที่เกี่ยวข้องกับกรณีข้อผิดพลาดดังนั้นจึงเป็นเรื่องจริงมากขึ้นคล้ายกับข้อยกเว้นกว่าEitherMaybe

ดังนั้นข้อดีของMaybe/ Eitherแนวทางคืออะไร? สำหรับหนึ่งคนมันเป็นพลเมืองชั้นหนึ่งของภาษา ลองเปรียบเทียบฟังก์ชั่นที่ใช้Eitherกับการโยนข้อยกเว้น สำหรับกรณียกเว้นการขอความช่วยเหลือที่แท้จริงเพียงอย่างเดียวของคุณคือtry...catchคำสั่ง สำหรับEitherฟังก์ชั่นนี้คุณสามารถใช้ combinators ที่มีอยู่เพื่อทำให้การควบคุมการไหลชัดเจนขึ้น นี่คือตัวอย่างบางส่วน:

ก่อนอื่นสมมติว่าคุณต้องการลองใช้ฟังก์ชั่นหลายอย่างที่อาจผิดพลาดในแถวจนกว่าคุณจะได้ฟังก์ชันที่ไม่เป็นเช่นนั้น หากคุณไม่ได้รับสิ่งใดโดยไม่มีข้อผิดพลาดคุณต้องการส่งคืนข้อความแสดงข้อผิดพลาดพิเศษ นี้เป็นจริงรูปแบบที่มีประโยชน์มาก try...catchแต่จะเป็นความเจ็บปวดที่น่ากลัวโดยใช้ อย่างมีความสุขเนื่องจากEitherเป็นเพียงค่าปกติคุณสามารถใช้ฟังก์ชั่นที่มีอยู่เพื่อทำให้โค้ดมีความชัดเจนมากขึ้น:

firstThing <|> secondThing <|> throwError (SomeError "error message")

อีกตัวอย่างหนึ่งคือการมีฟังก์ชั่นเสริม สมมติว่าคุณมีหลายฟังก์ชันที่จะเรียกใช้รวมถึงฟังก์ชันที่พยายามปรับการสืบค้นให้เหมาะสม หากสิ่งนี้ล้มเหลวคุณต้องการให้ทุกอย่างทำงานอย่างอื่น คุณสามารถเขียนโค้ดบางอย่างเช่น:

do a <- getA
   b <- getB
   optional (optimize query)
   execute query a b

ทั้งสองกรณีนี้มีความชัดเจนและสั้นกว่าการใช้try..catchและที่สำคัญกว่านั้นคือความหมายมากขึ้น การใช้ฟังก์ชั่นเหมือน<|>หรือoptionalทำให้ความตั้งใจของคุณมากชัดเจนกว่าการใช้try...catchที่มักจะจัดการกับข้อยกเว้น

โปรดทราบว่าคุณไม่จำเป็นต้องทิ้งรหัสของคุณด้วยบรรทัดเช่นif a == Nothing then Nothing else ...! จุดรวมของการรักษาMaybeและEitherในฐานะ Monad คือการหลีกเลี่ยงสิ่งนี้ คุณสามารถเข้ารหัสซีแมนทิกส์การแพร่กระจายในฟังก์ชันผูกเพื่อให้คุณได้รับการตรวจสอบโมฆะ / ข้อผิดพลาดฟรี ครั้งเดียวที่คุณต้องตรวจสอบอย่างชัดเจนคือถ้าคุณต้องการส่งคืนสิ่งอื่นนอกเหนือจากNothinga Nothingและแม้จะเป็นเรื่องง่าย: มีฟังก์ชั่นไลบรารีมาตรฐานมากมายที่จะทำให้โค้ดนั้นดีกว่า

ในที่สุดข้อดีอีกอย่างหนึ่งก็คือMaybe/ Eitherพิมพ์ง่ายขึ้น ไม่จำเป็นต้องขยายภาษาด้วยคำหลักเพิ่มเติมหรือโครงสร้างการควบคุมทุกอย่างเป็นเพียงห้องสมุด เนื่องจากพวกเขากำลังเพียงค่าปกติก็จะทำให้ระบบการพิมพ์ที่ง่าย - ใน Java คุณต้องแยกความแตกต่างระหว่างประเภท (เช่นพิมพ์กลับ) และผลกระทบ (เช่นthrowsงบ) Maybeซึ่งคุณจะไม่ได้ใช้ พวกเขายังทำงานเหมือนคนอื่น ๆ ประเภทที่ผู้ใช้กำหนด - ไม่จำเป็นต้องมีรหัสการจัดการข้อผิดพลาดพิเศษอบเป็นภาษา

การชนะอีกครั้งคือMaybe/ Eitherเป็น functors และ monads ซึ่งหมายความว่าพวกเขาสามารถใช้ประโยชน์จากฟังก์ชั่นการควบคุม monad ที่มีอยู่ (ซึ่งมีจำนวนที่พอใช้) และโดยทั่วไปแล้วก็เล่นกับ monads อื่น ๆ

ที่กล่าวว่ามีบางประการ สำหรับหนึ่งค่าMaybeมิได้Eitherแทนที่ไม่ จำกัดข้อยกเว้น คุณจะต้องการวิธีอื่นในการจัดการสิ่งต่าง ๆ เช่นการหารด้วย 0 เพียงเพราะมันเป็นความเจ็บปวดที่ทุกฝ่ายจะคืนMaybeค่า

ปัญหาอื่นคือการส่งคืนข้อผิดพลาดหลายประเภท (ใช้กับEither) ด้วยข้อยกเว้นคุณสามารถโยนข้อยกเว้นประเภทต่าง ๆ ในฟังก์ชั่นเดียวกันได้ ด้วยEitherคุณจะได้รับเพียงหนึ่งประเภท สิ่งนี้สามารถเอาชนะได้ด้วยการพิมพ์ย่อยหรือ ADT ที่มีข้อผิดพลาดประเภทต่าง ๆ ทั้งหมดเป็นตัวสร้าง (วิธีที่สองนี้เป็นวิธีที่มักใช้ใน Haskell)

ถึงกระนั้นฉันก็ชอบวิธีMaybe/ Eitherเพราะฉันคิดว่ามันง่ายและยืดหยุ่นกว่า


ตกลงกันเป็นส่วนใหญ่ แต่ฉันไม่คิดว่าตัวอย่าง "ทางเลือก" สมเหตุสมผล - ดูเหมือนว่าคุณสามารถทำได้เช่นกันพร้อมกับข้อยกเว้น: เป็นโมฆะตัวเลือก (การกระทำ Action) {ลอง {act (); } catch (Exception) {}}
Errorsatz

11
  1. ข้อยกเว้นสามารถนำข้อมูลเพิ่มเติมเกี่ยวกับแหล่งที่มาของปัญหา OpenFile()สามารถขว้างFileNotFoundหรือNoPermissionหรือTooManyDescriptorsอื่น ๆ ได้ A ไม่มีใครไม่พกข้อมูลนี้
  2. ข้อยกเว้นสามารถใช้ในบริบทที่ไม่มีค่าส่งคืน (เช่นกับตัวสร้างในภาษาที่มี)
  3. ข้อยกเว้นช่วยให้คุณสามารถส่งข้อมูลขึ้นสแต็กได้อย่างง่ายดายโดยไม่มีif None return Noneคำสั่งสไตล์จำนวนมาก
  4. การจัดการข้อยกเว้นมีผลกระทบต่อประสิทธิภาพการทำงานสูงกว่าการส่งคืนค่าเกือบทุกครั้ง
  5. สิ่งสำคัญที่สุดคือทั้งหมดข้อยกเว้นและอาจจะมีจุดประสงค์ที่แตกต่างกัน - monad มีการใช้เพื่อระบุถึงปัญหาในขณะที่อาจจะไม่ใช่

    “ พยาบาลถ้ามีผู้ป่วยในห้องที่ 5 คุณช่วยให้เขารอได้ไหม?”

    • อาจจะเป็น monad: "หมอไม่มีผู้ป่วยอยู่ในห้อง 5. "
    • ข้อยกเว้น: "หมอไม่มีห้อง 5!"

    (แจ้งให้ทราบว่า "ถ้า" - นี่หมายถึงแพทย์คาดหวังว่าอาจจะ monad)


7
ฉันไม่เห็นด้วยกับประเด็นที่ 2 และ 3 โดยเฉพาะอย่างยิ่ง 2 ไม่ได้ก่อให้เกิดปัญหาในภาษาที่ใช้พระเพราะภาษาเหล่านั้นมีการประชุมที่ไม่สร้างปริศนาที่ต้องจัดการกับความล้มเหลวในระหว่างการก่อสร้าง เกี่ยวกับ 3 ภาษาที่มี monads มีไวยากรณ์ที่เหมาะสมสำหรับการจัดการ monads ในลักษณะโปร่งใสที่ไม่ต้องการการตรวจสอบที่ชัดเจน (เช่นNoneค่าสามารถแพร่กระจายได้) จุดที่ 5 ของคุณเป็นสิ่งที่ถูกต้องเท่านั้น…คำถามคือ: สถานการณ์ใดที่มีความพิเศษอย่างไม่น่าสงสัย? มันจะเปิดออก ... ไม่มาก
Konrad Rudolph

3
เกี่ยวกับ (2) คุณสามารถเขียนbindในลักษณะที่การทดสอบNoneไม่ได้เกิดขึ้นกับค่าใช้จ่ายเกี่ยวกับวากยสัมพันธ์ ตัวอย่างที่ง่ายมาก C # เพิ่งโอเวอร์โหลดตัวNullableดำเนินการอย่างเหมาะสม ไม่มีการตรวจสอบที่Noneจำเป็นแม้เมื่อใช้งานชนิด แน่นอนว่าการตรวจสอบยังคงดำเนินการอยู่ (มันปลอดภัยสำหรับพิมพ์) แต่อยู่เบื้องหลังและไม่เกะกะรหัสของคุณ เช่นเดียวกับในบางแง่มุมของการคัดค้านของคุณต่อการคัดค้านของฉันถึง (5) แต่ฉันยอมรับว่ามันอาจไม่ได้นำไปใช้เสมอ
Konrad Rudolph

4
@Oak: เกี่ยวกับ (3) จุดรวมของการปฏิบัติMaybeเป็น monad คือการทำให้การถ่ายทอดNoneโดยปริยาย ซึ่งหมายความว่าหากคุณต้องการNoneรับคืนNoneคุณไม่ต้องเขียนรหัสพิเศษใด ๆ เลย Noneครั้งเดียวที่คุณต้องแข่งขันคือถ้าคุณต้องการที่จะทำบางสิ่งบางอย่างเป็นพิเศษเกี่ยวกับ คุณไม่จำเป็นต้องif None then Noneเรียงลำดับของข้อความ
Tikhon Jelvis

5
@ โอ๊ค: จริง แต่นั่นไม่ใช่จุดของฉัน สิ่งที่ผมพูดคือว่าคุณจะได้รับnullการตรวจสอบว่าเป็นเช่นนั้น (เช่นif Nothing then Nothing) ให้ฟรีเพราะMaybeเป็น monad มันเข้ารหัสในความหมายของการผูก ( >>=) Maybeสำหรับ
Tikhon Jelvis

2
นอกจากนี้เกี่ยวกับ (1): คุณสามารถจะเขียน monad ที่สามารถนำข้อมูลข้อผิดพลาด (เช่นEither) Maybeที่พฤติกรรมเช่นเดียวกับ สลับไปมาระหว่างทั้งสองเป็นจริงค่อนข้างง่ายเพราะเป็นจริงเพียงกรณีพิเศษของMaybe Either(ใน Haskell คุณอาจคิดว่าMaybeเป็นEither ().)
ทิคฮอน Jelvis

6

"อาจจะ" ไม่ใช่การทดแทนสำหรับข้อยกเว้น ข้อยกเว้นมีไว้เพื่อใช้ในกรณีพิเศษ (ตัวอย่างเช่น: การเปิดการเชื่อมต่อ db และเซิร์ฟเวอร์ db ไม่อยู่ที่นั่นแม้ว่ามันควรจะเป็น) "อาจจะ" สำหรับการสร้างแบบจำลองสถานการณ์เมื่อคุณอาจหรืออาจมีค่าที่ถูกต้อง; สมมติว่าคุณได้รับค่าจากพจนานุกรมสำหรับคีย์: อาจมีหรือไม่มี - ไม่มีอะไร "พิเศษ" เกี่ยวกับผลลัพธ์เหล่านี้


2
อันที่จริงฉันมีรหัสค่อนข้างน้อยเกี่ยวกับพจนานุกรมที่มีคีย์ที่หายไปหมายถึงสิ่งที่ผิดพลาดอย่างน่ากลัวในบางจุดน่าจะเป็นข้อผิดพลาดในรหัสของฉันหรือในรหัสที่แปลงอินพุตเป็นสิ่งที่ใช้ในจุดนั้น

3
@delnan: ฉันไม่ได้บอกว่าค่าที่หายไปไม่สามารถเป็นสัญญาณบ่งบอกถึงสถานะพิเศษได้ - มันไม่จำเป็นต้องเป็นอย่างนั้น บางทีอาจจำลองสถานการณ์ที่ตัวแปรอาจมีหรือไม่มีค่าที่ถูกต้อง - คิดว่าเป็นประเภทที่ไม่มีค่าใน C #
Nemanja Trifunovic

6

ฉันคำตอบที่สองของ Tikhon แต่ฉันคิดว่ามันมีจุดปฏิบัติที่สำคัญมากที่ทุกคนขาดหายไป:

  1. กลไกการจัดการข้อยกเว้นอย่างน้อยก็ในภาษากระแสหลักนั้นเชื่อมโยงกับแต่ละหัวข้ออย่างใกล้ชิด
  2. Eitherกลไกไม่ได้คู่กับหัวข้อที่ทุกคน

ดังนั้นสิ่งที่เราเห็นทุกวันนี้ในชีวิตจริงคือโซลูชั่นการเขียนโปรแกรมแบบอะซิงโครนัสจำนวนมากกำลังนำเอารูปEitherแบบของการจัดการข้อผิดพลาดมาใช้ พิจารณาสัญญา Javascript ตามรายละเอียดในลิงก์ใด ๆ เหล่านี้:

แนวคิดของสัญญาอนุญาตให้คุณเขียนโค้ดแบบอะซิงโครนัสเช่นนี้ (นำมาจากลิงก์สุดท้าย):

var greetingPromise = sayHello();
greetingPromise
    .then(addExclamation)
    .then(function (greeting) {
        console.log(greeting);    // 'hello world!!!!’
    }, function(error) {
        console.error('uh oh: ', error);   // 'uh oh: something bad happened’
    });

โดยทั่วไปสัญญาเป็นวัตถุที่:

  1. แสดงผลลัพธ์ของการคำนวณแบบอะซิงโครนัสซึ่งอาจหรืออาจยังไม่เสร็จ
  2. ช่วยให้คุณเชื่อมโยงการดำเนินการเพิ่มเติมเพื่อดำเนินการกับผลลัพธ์ซึ่งจะถูกเรียกใช้เมื่อผลลัพธ์นั้นพร้อมใช้งานและมีผลลัพธ์ใดบ้างตามที่สัญญาไว้
  3. ช่วยให้คุณเชื่อมต่อตัวจัดการความล้มเหลวที่จะเรียกใช้หากการคำนวณของสัญญาล้มเหลว หากไม่มีตัวจัดการข้อผิดพลาดจะถูกส่งไปยังตัวจัดการในภายหลังในสายโซ่

โดยพื้นฐานแล้วเนื่องจากการสนับสนุนข้อยกเว้นดั้งเดิมของภาษาไม่ทำงานเมื่อการคำนวณของคุณเกิดขึ้นในหลายเธรดการใช้งานตามสัญญาจะต้องมีกลไกการจัดการข้อผิดพลาดและสิ่งเหล่านี้กลายเป็นพระคล้ายกับประเภทMaybe/ HaskellEither


ไม่มีสิ่งที่ต้องทำกับเธรด JavaScript ในเบราว์เซอร์จะทำงานในหัวข้อเดียวเสมอไม่ได้อยู่ในหลายเธรด แต่คุณยังไม่สามารถใช้ข้อยกเว้นได้เนื่องจากคุณไม่รู้ว่าเมื่อไรที่ฟังก์ชันของคุณถูกเรียกใช้ในอนาคต อะซิงโครนัสไม่ได้หมายถึงการมีส่วนร่วมของเธรดโดยอัตโนมัติ นั่นเป็นเหตุผลที่คุณไม่สามารถทำงานกับข้อยกเว้นได้ คุณสามารถดึงข้อยกเว้นถ้าคุณเรียกใช้ฟังก์ชันและทันทีที่ได้รับการดำเนินการ แต่จุดประสงค์ทั้งหมดของ Asynchronous คือมันจะทำงานในอนาคตบ่อยครั้งเมื่อบางสิ่งบางอย่างเสร็จสิ้นและไม่ใช่ในทันที นั่นเป็นเหตุผลที่คุณไม่สามารถใช้ข้อยกเว้นได้
David Raab

1

ระบบประเภท Haskell จะกำหนดให้ผู้ใช้ต้องยอมรับความเป็นไปได้ของ a Nothingในขณะที่ภาษาการเขียนโปรแกรมมักไม่ต้องการข้อยกเว้น ซึ่งหมายความว่าเราจะทราบในเวลารวบรวมว่าผู้ใช้ได้ตรวจสอบข้อผิดพลาด


1
มีการตรวจสอบข้อยกเว้นใน Java และบ่อยครั้งที่ผู้คนปฏิบัติต่อพวกเขาอย่างรุนแรง
Vladimir

1
@ DairT'arg ButJava ต้องการการตรวจสอบข้อผิดพลาด IO (เป็นตัวอย่าง) แต่ไม่ใช่สำหรับ NPE ใน Haskell เป็นวิธีอื่น: ตรวจสอบค่า null (บางที) แต่ข้อผิดพลาด IO เพียงแค่โยนข้อยกเว้น (ไม่ถูกตรวจสอบ) ฉันไม่แน่ใจว่าจะสร้างความแตกต่างได้มากน้อยเพียงใด แต่ฉันไม่ได้ยินว่า Haskeller บ่นเกี่ยวกับบางทีและฉันคิดว่าผู้คนจำนวนมากต้องการให้มีการตรวจสอบ NPEs

1
@delnan ผู้คนต้องการให้มีการตรวจสอบ NPE หรือไม่ พวกเขาจะต้องบ้า และฉันหมายความว่า การทำให้ NPE ถูกตรวจสอบแล้วจะสมเหตุสมผลถ้าคุณมีวิธีหลีกเลี่ยงในตอนแรก (โดยมีการอ้างอิงที่ไม่เป็นโมฆะซึ่ง Java ไม่ได้มี)
Konrad Rudolph

5
@ KonradRudolph ใช่ผู้คนอาจไม่ต้องการให้มีการตรวจสอบในแง่ที่ว่าพวกเขาจะต้องเพิ่มthrows NPEลายเซ็นcatch(...) {throw ...} ให้กับทุก ๆลายเซ็นและทุกส่วนของเมธอดเดียว แต่ฉันเชื่อว่ามีตลาดสำหรับการตรวจสอบในลักษณะเดียวกับอาจจะเป็น: ความถูกต้องเป็นตัวเลือกและติดตามในระบบประเภท

1
@delnan อาแล้วฉันเห็นด้วย
Konrad Rudolph

0

บางทีโมนาอาจเป็นแบบเดียวกับการตรวจสอบ "null หมายถึงข้อผิดพลาด" ของภาษากระแสหลักส่วนใหญ่ (ยกเว้นมันจะต้องตรวจสอบค่าว่าง) และมีข้อดีและข้อเสียเหมือนกัน


8
ก็ไม่ได้มีข้อเสียเหมือนกันเพราะสามารถตรวจสอบประเภทแบบคงที่เมื่อใช้อย่างถูกต้อง ไม่มีข้อยกเว้นตัวชี้โมฆะเทียบเท่าเมื่อใช้บางที monads (อีกครั้งสมมติว่าพวกเขาใช้อย่างถูกต้อง)
Konrad Rudolph

จริง คุณคิดว่าควรจะชี้แจงอย่างไร
Telastyn

@ Konrad นั่นเป็นเพราะเพื่อที่จะใช้ค่า (อาจจะ) ในบางทีคุณต้องตรวจสอบไม่มี (แม้ว่าแน่นอนว่ามีความสามารถในการตรวจสอบจำนวนมากโดยอัตโนมัติ) ภาษาอื่น ๆ เก็บคู่มือประเภทนั้นไว้ (ส่วนใหญ่ด้วยเหตุผลทางปรัชญาที่ฉันเชื่อ)
Donal Fellows

2
@ Donal ใช่ แต่โปรดทราบว่าภาษาส่วนใหญ่ที่ใช้ Monads นั้นจะให้น้ำตาลประโยคที่เหมาะสมเพื่อให้การตรวจสอบนี้สามารถซ่อนอยู่ได้อย่างสมบูรณ์ เช่นคุณสามารถเพิ่มMaybeตัวเลขสองตัวโดยเขียนa + b โดยไม่จำเป็นต้องตรวจสอบNoneและผลลัพธ์จะเป็นค่าที่เลือกได้อีกครั้ง
Konrad Rudolph

2
การเปรียบเทียบกับประเภท nullable ถือเป็นจริงสำหรับMaybe ประเภทแต่การใช้Maybeเป็น monad เพิ่มน้ำตาลไวยากรณ์ที่ช่วยให้การแสดงตรรกะ null-ish มากขึ้นอย่างหรูหรา
tammammers

0

การจัดการข้อยกเว้นอาจเป็นความเจ็บปวดอย่างแท้จริงสำหรับแฟและการทดสอบ ฉันรู้ว่าหลามให้ "กับ" ไวยากรณ์ที่ดีที่ช่วยให้คุณสามารถดักจับข้อยกเว้นโดยไม่มีบล็อก "ลอง ... จับ" ที่เข้มงวด ตัวอย่างเช่นใน Java ลองใช้ catch catch block ที่มีขนาดใหญ่สำเร็จรูปทั้งแบบ verbose หรือ verbose ที่มากและยากที่จะสลาย ยิ่งไปกว่านั้น Java ยังเพิ่มเสียงรบกวนทั้งหมดที่มีการตรวจสอบและข้อยกเว้นที่ไม่ได้ตรวจสอบ

หากคุณจับข้อยกเว้นและปฏิบัติต่อพวกเขาเป็นคุณสมบัติของพื้นที่ monadic แทนการประมวลผลที่ผิดปกติคุณสามารถผสมและจับคู่ฟังก์ชันที่คุณผูกไว้ในพื้นที่นั้นโดยไม่คำนึงถึงสิ่งที่พวกเขาโยนหรือจับ

ถ้ายังดีกว่า monad ของคุณจะป้องกันเงื่อนไขที่อาจเกิดข้อยกเว้นได้ (เช่นการกดปุ่มเช็คอินเป็น null บางที) ก็ดีกว่า ถ้า ... ถ้าอย่างนั้นจะมากง่ายกว่าที่จะแยกตัวประกอบและทดสอบกว่าลอง ... จับ

จากสิ่งที่ฉันได้เห็น Go คือการใช้วิธีการที่คล้ายกันโดยระบุว่าแต่ละฟังก์ชั่นกลับมา (คำตอบข้อผิดพลาด) นั่นเป็นแบบเดียวกับ "การยก" ฟังก์ชั่นลงในช่องว่าง monad ที่ประเภทคำตอบหลักถูกตกแต่งด้วยข้อบ่งชี้ข้อผิดพลาดและข้อยกเว้นการขว้างปาและจับได้อย่างมีประสิทธิภาพ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.