ในการเคารพผู้อ่านที่รวดเร็วฉันเริ่มต้นด้วยคำจำกัดความที่แม่นยำก่อนดำเนินการต่อด้วยคำอธิบาย "ภาษาอังกฤษธรรมดา" ที่รวดเร็วยิ่งขึ้นแล้วเลื่อนไปที่ตัวอย่าง
นี่คือทั้งกระชับและนิยาม reworded เล็กน้อย
monad (วิทยาการคอมพิวเตอร์) อย่างเป็นทางการของแผนที่ที่:
ส่งทุกชนิดX
ของภาษาการเขียนโปรแกรมที่กำหนดไปยังชนิดใหม่T(X)
(เรียกว่า "ชนิดของT
-computations ด้วยค่าในX
");
พร้อมกับกฎสำหรับการเขียนสองฟังก์ชั่นของแบบฟอร์ม
f:X->T(Y)
และg:Y->T(Z)
ฟังก์ชั่นg∘f:X->T(Z)
;
ในลักษณะที่เชื่อมโยงกันในความรู้สึกที่ชัดเจนและเป็นเอกภาพด้วยความเคารพต่อหน่วยงานที่ได้รับเรียกว่าpure_X:X->T(X)
ให้คิดว่าเป็นคุณค่าของการคำนวณที่บริสุทธิ์เพียงแค่คืนค่านั้น
ดังนั้นในคำง่าย ๆmonadคือกฎที่ส่งผ่านจากประเภทหนึ่งX
ไปยังอีกประเภทหนึ่งT(X)
และกฎที่จะส่งผ่านจากสองฟังก์ชันf:X->T(Y)
และg:Y->T(Z)
(ที่คุณต้องการเขียน แต่ไม่สามารถ) ไปยังฟังก์ชันใหม่h:X->T(Z)
ได้ ซึ่งอย่างไรก็ตามไม่ใช่องค์ประกอบในแง่คณิตศาสตร์อย่างเข้มงวด โดยพื้นฐานแล้วเรามีองค์ประกอบ "ดัด" ของฟังก์ชั่นหรือกำหนดวิธีการประกอบฟังก์ชั่นใหม่
นอกจากนี้เราต้องการกฎของการเขียน monad เพื่อตอบสนองความจริงทางคณิตศาสตร์ "ชัดเจน":
- การเชื่อมโยง : การเขียน
f
ด้วยg
และจากนั้นกับh
(จากภายนอก) ควรจะเหมือนกับการเขียนg
ด้วยh
และจากนั้นกับf
(จากภายใน)
- คุณสมบัติ Unital : การเขียน
f
กับตัวตนของf
ฟังก์ชั่นทั้งสองข้างควรผลผลิต
อีกครั้งในคำง่ายๆเราไม่สามารถบ้านิยามองค์ประกอบของฟังก์ชั่นของเราอีกครั้งได้ตามที่เราต้องการ:
- ก่อนอื่นเราต้องมีการเชื่อมโยงเพื่อให้สามารถเขียนฟังก์ชั่นได้หลายอย่างในแถว
f(g(h(k(x)))
เดียวและไม่ต้องกังวลกับการระบุฟังก์ชั่นการเรียงลำดับคู่ เมื่อกฎ monad กำหนดวิธีการเขียนฟังก์ชั่นคู่หนึ่งโดยปราศจากความจริงเราจะต้องรู้ว่าคู่ใดประกอบกันก่อน (โปรดทราบว่าแตกต่างจากคุณสมบัติการสับเปลี่ยนที่f
ประกอบด้วยg
เหมือนกันg
กับf
ซึ่งไม่จำเป็นต้องใช้)
- และประการที่สองเราต้องการคุณสมบัติที่เป็นเอกภาพซึ่งก็คือการพูดว่าอัตลักษณ์นั้นประกอบไปด้วยวิธีที่เราคาดหวังไว้เล็กน้อย ดังนั้นเราสามารถ refactor ได้อย่างปลอดภัยฟังก์ชั่นเมื่อใดก็ตามที่สามารถดึงตัวตนเหล่านั้น
ดังนั้นอีกครั้งโดยย่อ: Monad เป็นกฎของการขยายประเภทและฟังก์ชั่นการเขียนที่ตอบสนองความจริงสองประการคือความสัมพันธ์และคุณสมบัติที่เป็นเอกภาพ
ในแง่ของการปฏิบัติคุณต้องการให้ monad ถูกนำไปใช้กับคุณโดยภาษาคอมไพเลอร์หรือกรอบงานที่จะดูแลฟังก์ชั่นการเขียนสำหรับคุณ ดังนั้นคุณสามารถมุ่งเน้นไปที่การเขียนตรรกะของฟังก์ชั่นของคุณมากกว่าที่จะกังวลว่าจะมีการใช้งานการดำเนินการอย่างไร
ที่เป็นหลักมันสั้น
เป็นนักคณิตศาสตร์มืออาชีพฉันชอบที่จะหลีกเลี่ยงการเรียกh
ว่า "องค์ประกอบ" ของและf
g
เพราะในทางคณิตศาสตร์มันไม่ใช่ เรียกว่า "การจัดองค์ประกอบ" อย่างไม่ถูกต้องสันนิษฐานว่าh
เป็นองค์ประกอบทางคณิตศาสตร์ที่แท้จริงซึ่งมันไม่ใช่ มันไม่ได้กำหนดไว้โดยไม่ซ้ำกันและf
g
แต่เป็นผลจากฟังก์ชั่น "กฎการเขียน" ใหม่ของเรา ซึ่งสามารถแตกต่างอย่างสิ้นเชิงจากองค์ประกอบทางคณิตศาสตร์ที่เกิดขึ้นจริงแม้ว่าจะมีอยู่หลัง!
เพื่อให้มันแห้งน้อยลงขอให้ฉันลองอธิบายด้วยตัวอย่างว่าฉันใส่คำอธิบายประกอบเป็นส่วนเล็ก ๆ เพื่อให้คุณสามารถข้ามไปยังจุดนั้นได้
ข้อยกเว้นการขว้างเป็นตัวอย่างของ Monad
สมมติว่าเราต้องการเขียนสองฟังก์ชัน:
f: x -> 1 / x
g: y -> 2 * y
แต่f(0)
ไม่ได้กำหนดไว้ดังนั้นจึงมีข้อe
ผิดพลาดเกิดขึ้น จากนั้นคุณจะกำหนดค่าองค์ประกอบได้g(f(0))
อย่างไร โยนข้อยกเว้นอีกครั้งแน่นอน! e
บางทีเดียวกัน e1
อาจจะยกเว้นการปรับปรุงใหม่
เกิดอะไรขึ้นที่นี่อย่างแม่นยำ? ก่อนอื่นเราต้องการค่าข้อยกเว้นใหม่ (ต่างกันหรือเหมือนกัน) คุณสามารถเรียกพวกเขาnothing
หรือnull
อะไรก็ตาม แต่สาระสำคัญยังคงเหมือนเดิม - พวกเขาควรจะเป็นค่าใหม่เช่นไม่ควรเป็นnumber
ตัวอย่างในที่นี่ของเรา ฉันไม่ต้องการเรียกพวกเขาnull
เพื่อหลีกเลี่ยงความสับสนกับวิธีnull
การใช้งานในภาษาเฉพาะใด ๆ ฉันชอบหลีกเลี่ยงอย่างเท่าเทียมกันnothing
เพราะมันมักจะเกี่ยวข้องกับnull
ซึ่งโดยหลักการแล้วสิ่งที่null
ควรทำอย่างไรหลักการนั้นมักจะถูกทำให้งอด้วยเหตุผลอะไรก็ตาม
อะไรคือข้อยกเว้น?
นี่เป็นเรื่องเล็กน้อยสำหรับโปรแกรมเมอร์ที่มีประสบการณ์ แต่ฉันอยากจะพูดอะไรซักอย่างเพื่อกำจัดหนอนแห่งความสับสน:
ข้อยกเว้นเป็นวัตถุที่ห่อหุ้มข้อมูลเกี่ยวกับวิธีการที่ผลลัพธ์ที่ไม่ถูกต้องของการดำเนินการเกิดขึ้น
สิ่งนี้สามารถอยู่ในช่วงจากการทิ้งรายละเอียดใด ๆ และส่งกลับค่าส่วนกลางเดียว (เช่นNaN
หรือnull
) หรือสร้างรายการบันทึกที่ยาวนานหรือสิ่งที่เกิดขึ้นส่งไปยังฐานข้อมูลและทำซ้ำทั่วชั้นจัดเก็บข้อมูลแบบกระจาย;)
แตกต่างที่สำคัญระหว่างทั้งสองตัวอย่างรุนแรงของข้อยกเว้นคือว่าในกรณีแรกที่มีไม่มีผลข้างเคียง ในครั้งที่สองมี ซึ่งนำเราไปสู่คำถาม (พันดอลลาร์):
มีข้อยกเว้นในฟังก์ชั่นแท้หรือไม่
คำตอบที่สั้นกว่า : ใช่ แต่เฉพาะเมื่อไม่มีผลข้างเคียง
คำตอบอีกต่อไป เพื่อให้บริสุทธิ์เอาต์พุตของฟังก์ชั่นของคุณจะต้องได้รับการพิจารณาโดยไม่ซ้ำกันโดยอินพุต ดังนั้นเราจึงแก้ไขฟังก์ชันของเราf
โดยส่ง0
ค่านามธรรมใหม่e
ที่เราเรียกว่าข้อยกเว้น เราตรวจสอบให้แน่ใจว่าค่ามีข้อมูลภายนอกที่ไม่มีไม่ได้กำหนดที่ไม่ซ้ำกันโดยการป้อนข้อมูลของเราซึ่งเป็นe
x
ดังนั้นนี่คือตัวอย่างของข้อยกเว้นที่ไม่มีผลข้างเคียง:
e = {
type: error,
message: 'I got error trying to divide 1 by 0'
}
และนี่คือสิ่งเดียวที่มีผลข้างเคียง:
e = {
type: error,
message: 'Our committee to decide what is 1/0 is currently away'
}
ที่จริงแล้วมันมีผลข้างเคียงหากข้อความนั้นสามารถเปลี่ยนแปลงได้ในอนาคต แต่ถ้ามันรับประกันว่าจะไม่เปลี่ยนแปลงค่านั้นจะสามารถคาดการณ์ได้โดยไม่ซ้ำกันดังนั้นจึงไม่มีผลข้างเคียง
ที่จะทำให้มันยิ่งงอน ฟังก์ชั่นที่กลับมา42
มีความบริสุทธิ์อย่างชัดเจน แต่ถ้าใครบางคนบ้าตัดสินใจที่จะสร้าง42
ตัวแปรที่ค่าอาจมีการเปลี่ยนแปลงฟังก์ชั่นเดียวกันมากหยุดบริสุทธิ์ภายใต้เงื่อนไขใหม่
โปรดทราบว่าฉันกำลังใช้สัญกรณ์ตัวอักษรสำหรับความเรียบง่ายเพื่อแสดงให้เห็นถึงสาระสำคัญ น่าเสียดายที่สิ่งต่าง ๆ เกิดความสับสนในภาษาอย่างจาวาสคริปต์ซึ่งerror
ไม่ใช่ประเภทที่ทำงานในแบบที่เราต้องการในส่วนของฟังก์ชั่นในขณะที่ประเภทที่แท้จริงเช่นnull
หรือNaN
ไม่ทำงานในลักษณะนี้ แต่จะผ่านสิ่งประดิษฐ์บางอย่าง การแปลงประเภท
ประเภทส่วนขยาย
ในขณะที่เราต้องการเปลี่ยนแปลงข้อความภายในข้อยกเว้นของเราเราจะประกาศประเภทใหม่E
สำหรับวัตถุข้อยกเว้นทั้งหมดแล้วนั่นคือสิ่งที่maybe number
นอกเหนือจากชื่อที่สับสนซึ่งจะเป็นประเภทnumber
หรือประเภทข้อยกเว้นใหม่E
ดังนั้นมันเป็นจริงสหภาพnumber | E
ของและnumber
E
โดยเฉพาะอย่างยิ่งมันขึ้นอยู่กับวิธีการที่เราต้องการที่จะสร้างซึ่งไม่มีปัญหามิได้สะท้อนให้เห็นในชื่อE
maybe number
องค์ประกอบการทำงานคืออะไร?
มันเป็นเรื่องที่ดำเนินการทางคณิตศาสตร์การฟังก์ชั่น
f: X -> Y
และg: Y -> Z
และการสร้างองค์ประกอบของพวกเขาเป็นฟังก์ชั่นที่น่าพอใจh: X -> Z
h(x) = g(f(x))
ปัญหาเกี่ยวกับคำนิยามนี้เกิดขึ้นเมื่อผลที่ไม่ได้รับอนุญาตเป็นข้อโต้แย้งของf(x)
g
ในวิชาคณิตศาสตร์ฟังก์ชั่นเหล่านั้นไม่สามารถประกอบได้หากไม่มีงานพิเศษ การแก้ปัญหาทางคณิตศาสตร์อย่างเคร่งครัดสำหรับตัวอย่างข้างต้นของเราf
และg
คือการลบจากชุดของคำจำกัดความของ0
f
กับที่ชุดใหม่ของคำนิยาม (แบบใหม่ที่เข้มงวดมากขึ้นของx
) f
กลายเป็น composable g
กับ
อย่างไรก็ตามมันไม่ได้เป็นประโยชน์ในการเขียนโปรแกรมเพื่อ จำกัด ชุดของคำจำกัดความf
เช่นนั้น สามารถใช้ข้อยกเว้นแทนได้
หรือเป็นอีกวิธีหนึ่งคุณค่าเทียมที่ถูกสร้างขึ้นเช่นNaN
, undefined
, null
, Infinity
ฯลฯ ดังนั้นคุณประเมิน1/0
การInfinity
และการ1/-0
-Infinity
จากนั้นบังคับค่าใหม่ให้กลับไปสู่นิพจน์ของคุณแทนการโยนข้อยกเว้น นำไปสู่ผลลัพธ์ที่คุณอาจจะหรืออาจจะไม่สามารถคาดเดาได้:
1/0 // => Infinity
parseInt(Infinity) // => NaN
NaN < 0 // => false
false + 1 // => 1
และเรากลับไปที่หมายเลขปกติพร้อมที่จะไป;)
JavaScript ช่วยให้เราสามารถดำเนินการนิพจน์ที่เป็นตัวเลขได้ในค่าใช้จ่ายใด ๆ โดยไม่ทิ้งข้อผิดพลาดดังตัวอย่างด้านบน นั่นหมายความว่ามันยังช่วยให้การเขียนฟังก์ชั่น ซึ่งเป็นสิ่งที่เกี่ยวกับ monad - มันเป็นกฎในการเขียนฟังก์ชั่นที่ตอบสนองความจริงตามที่กำหนดไว้ในตอนต้นของคำตอบนี้
แต่กฎของฟังก์ชั่นการเขียนเกิดขึ้นจากการใช้งาน JavaScript เพื่อจัดการกับข้อผิดพลาดที่เป็นตัวเลขหรือไม่?
ในการตอบคำถามนี้สิ่งที่คุณต้องทำคือตรวจสอบความจริง (จากการออกกำลังกายไม่ใช่ส่วนหนึ่งของคำถามที่นี่;)
สามารถใช้ข้อยกเว้นในการขว้างปาเพื่อสร้าง Monad ได้หรือไม่?
แท้จริง monad มีประโยชน์มากขึ้นแทนจะกำหนดกฎว่าถ้าf
โยนข้อยกเว้นสำหรับบางคนจึงไม่องค์ประกอบใด ๆx
g
บวกทำให้ข้อยกเว้นE
ทั่วโลกมีความเป็นไปได้เพียงค่าเดียวเท่านั้น ( วัตถุเทอร์มินัลในทฤษฎีหมวดหมู่) ตอนนี้สัจพจน์ทั้งสองสามารถตรวจสอบได้ทันทีและเราได้รับ monad ที่มีประโยชน์มาก และผลที่ได้คือสิ่งที่เป็นที่รู้จักกันดีในฐานะอาจ monad