นักพัฒนาคนหนึ่งได้จุดประกายการถกเถียงในชุมชนการเขียนโปรแกรมเชิงฟังก์ชันด้วยการโต้แย้งว่า monads ได้รับการประเมินค่าสูงเกินไป และเสนอ natural transformations เป็นทางเลือกที่มีความยืดหยุ่นมากกว่า การอภิปรายนี้มีจุดศูนย์กลางอยู่ที่ภาษาโปรแกรมที่เรียกว่า Я ( Ya ) ซึ่งใช้แนวทางที่ไม่เป็นไปตามแบบแผนในการจัดการกับผลกระทบเชิงคำนวณ
ข้อเสนอนี้แนะนำให้แยกย่อย monads ออกเป็นองค์ประกอบพื้นฐาน คือ functors ที่จับคู่กับ natural transformations แทนที่จะถือว่าเป็นโครงสร้างที่เป็นหน่วยเดียวกัน แนวทางนี้มีเป้าหมายเพื่อแก้ไขหนึ่งในความท้าทายที่ยังคงอยู่ในการเขียนโปรแกรมเชิงฟังก์ชัน คือ ความยากลำบากในการประกอบ monads ประเภทต่างๆ โดยไม่ต้องใช้ monad transformers เฉพาะทาง
การแยกส่วนประกอบของ Monad:
- η[i] (eta): การแปลงธรรมชาติที่ห่อหุ้มค่าต่างๆ เข้าไปในบริบทของ monadic (เทียบเท่ากับ
return
/pure
) - μ[i] (mu): การแปลงธรรมชาติที่ทำให้ชั้น monadic ที่ซ้อนกันแบนราบ (เทียบเท่ากับ
join
) - เงื่อนไขความสอดคล้อง: μ[i] ∘ η[i] = identity
ปฏิกิริยาของชุมชนมีตั้งแต่ความหลงใหลไปจนถึงความสับสน
การตอบสนองของชุมชนโปรแกรมเมอร์มีความหลากหลาย โดยนักพัฒนาจำนวนมากประสบปัญหาในการแยกแยะสัญลักษณ์ทางคณิตศาสตร์ที่หนาแน่นและไวยากรณ์ที่ไม่คุ้นเคย ผู้แสดงความคิดเห็นบางคนสังเกตว่าฐานโค้ดดูลึกลับและคล้ายกับการผสมผสานระหว่าง Haskell และ APL ซึ่งเป็นภาษาโปรแกรมอาร์เรย์ที่เป็นที่รู้จักจากสัญลักษณ์ที่เข้าใจยาก
แม้จะมีความซับซ้อน แต่สมาชิกชุมชนหลายคนก็ยังรับรู้ถึงรากฐานทางทฤษฎีของงานนี้ แนวทางดังกล่าวสร้างขึ้นบนแนวคิดทฤษฎีหมวดหมู่ที่มีการยอมรับอย่างดี โดยเฉพาะเกี่ยวกับ functors และ natural transformations ซึ่งเป็นรากฐานทางคณิตศาสตร์ของ monads เอง
Functors เป็นโครงสร้างทางคณิตศาสตร์ที่แมประหว่างหมวดหมู่ต่างๆ ในขณะที่ยังคงรักษาโครงสร้างของพวกมันไว้ Natural transformations ให้วิธีการที่เป็นระบบในการแปลงระหว่าง functors ต่างๆ
ระบบ Language Effects ของ Я :
- World: การดำเนินการ I/O และการโต้ตอบกับภายนอก
- State: การคำนวณแบบมีสถานะพร้อมการดำเนินการ get/set
- Stops: การจัดการข้อผิดพลาดและการสิ้นสุดก่อนกำหนด
- Jointed Effects: การรวมกันเช่น
(Stops reason 001 State state)
ที่อนุญาตให้มีการโต้ตอบระหว่างประเภทเอฟเฟกต์หลายแบบ
ปัญหาการประกอบและแนวทางแก้ไขที่เสนอ
Monads แบบดั้งเดิมเผชิญกับข้อจำกัดที่สำคัญ คือ ไม่สามารถประกอบเข้าด้วยกันได้อย่างง่ายดาย เมื่อนักพัฒนาต้องการรวมผลกระทบเชิงคำนวณที่แตกต่างกัน เช่น การจัดการสถานะและการจัดการข้อผิดพลาด พวกเขามักจะพึ่งพา monad transformers ซึ่งเป็นโครงสร้างเฉพาะทางที่อนุญาตให้ซ้อน monads ต่างๆ เข้าด้วยกัน
ระบบที่เสนอพยายามหลีกเลี่ยงปัญหานี้โดยการกำหนด natural transformations ที่สามารถบีบอัดชั้นของ functors ต่างๆ ให้เป็นโครงสร้างที่เป็นหน่วยเดียวกัน แทนที่จะถามว่า monads สองตัวสามารถประกอบเข้าด้วยกันได้หรือไม่ นักพัฒนาจะถามว่า natural transformation ที่จำเป็นมีอยู่ระหว่างผลกระทบที่ต้องการหรือไม่
Natural transformations เหล่านี้เทียบเท่ากับ type class instances ที่จำเป็นสำหรับ monad transformers คุณต้องมีวิธีการแปลงการคำนวณใน component monad ให้เป็นการคำนวณใน composed monad
Type class instances กำหนดวิธีที่ประเภทต่างๆ ใช้งานอินเทอร์เฟซทั่วไป ในขณะที่ monad transformers เป็นโครงสร้างที่รวมผลกระทบ monadic หลายๆ อย่างเข้าด้วยกัน
ตัวดำเนินการ Bind แบบดั้งเดิมเทียบกับที่เสนอใหม่:
- Haskell แบบดั้งเดิม:
(>>=): t a -> (a -> t b) -> t b
- ระบบที่เสนอใหม่:
(>>=): t a -> (a -> tt a) -> t a
- ความแตกต่างหลัก: ระบบที่เสนอใหม่ช่วยให้สามารถผูกเอฟเฟกต์ของประเภทต่างๆ ได้โดยไม่ต้องทำการ lifting อย่างชัดเจน
ผลกระทบในทางปฏิบัติยังไม่ชัดเจน
แม้ว่ากรอบทฤษฎีจะดูมีเหตุผล แต่ประโยชน์ในทางปฏิบัติเมื่อเทียบกับแนวทางที่มีอยู่ยังคงเป็นที่น่าสงสัย สมาชิกชุมชนหลายคนชี้ให้เห็นว่าระบบที่เสนอยังคงเผชิญกับความท้าทายด้านการขยายขนาดพื้นฐานเดียวกันกับ monad transformers คือ ปัญหา n-squared ที่ความซับซ้อนเพิ่มขึ้นแบบเอ็กซ์โพเนนเชียลตามจำนวนผลกระทบที่ถูกรวมเข้าด้วยกัน
ภาษา Я แสดงให้เห็นแนวคิดด้วยผลกระทบพื้นฐานสามประเภท คือ World (แทนการดำเนินการ I/O), State (สำหรับการคำนวณที่มีสถานะ), และ Stops (สำหรับการจัดการข้อผิดพลาด) อย่างไรก็ตาม นักวิจารณ์สังเกตว่าตัวอย่างที่ให้มานั้นมีข้อจำกัดและไม่ได้แสดงให้เห็นข้อได้เปรียบเหนือรูปแบบที่ยอมรับแล้วในภาษาอย่าง Haskell อย่างชัดเจน
การอภิปรายนี้เน้นย้ำถึงความตึงเครียดที่กำลังดำเนินอยู่ในการเขียนโปรแกรมเชิงฟังก์ชันระหว่างความบริสุทธิ์ทางคณิตศาสตร์และการใช้งานจริง แม้ว่าแนวทางที่เสนอจะให้ความสง่างามทางทฤษฎี แต่การประยุกต์ใช้ในโลกแห่งความเป็นจริงยังคงต้องได้รับการพิสูจน์ผ่านการยอมรับในวงกว้างและตัวอย่างที่ครอบคลุมมากขึ้น
การดำเนินการ I/O หมายถึงกิจกรรมการรับและส่งข้อมูล เช่น การอ่านไฟล์หรือการสื่อสารผ่านเครือข่าย การคำนวณที่มีสถานะเกี่ยวข้องกับการดำเนินการที่รักษาและปรับเปลี่ยนสถานะของโปรแกรมตลอดเวลา