ภาษาที่ไม่บริสุทธิ์ไม่ได้แตกต่างจากหลักการในภาษาบังคับที่คุ้นเคยมากขึ้นโดยเฉพาะอย่างยิ่งในตอนนี้ที่มีการลอกเลียนแบบการใช้งานมากมาย สไตล์ที่แตกต่างคืออะไร - คุณแก้ปัญหาอย่างไร
ไม่ว่าคุณจะนับ Haskell ว่าบริสุทธิ์หรือนับ IO monad เป็นสิ่งที่บริสุทธิ์สไตล์ Haskell เป็นรูปแบบที่รุนแรงของรูปแบบนี้และคุ้มค่ากับการเรียนรู้
Haskell IO monad มาจากทฤษฎีทางคณิตศาสตร์ของ monads (แน่นอน) อย่างไรก็ตามสำหรับโปรแกรมเมอร์ที่มีความจำเป็นฉันคิดว่าวิธีการย้อนกลับมาที่ monads นั้นสมเหตุสมผลดีกว่า
ขั้นตอนที่หนึ่ง - ภาษาที่ใช้งานได้จริงสามารถคืนค่าสตริงขนาดใหญ่ได้อย่างง่ายดายตามผลลัพธ์ สตริงขนาดใหญ่นี้สามารถเป็นซอร์สโค้ดของโปรแกรมที่จำเป็นซึ่งได้มาในลักษณะการทำงานที่บริสุทธิ์จากพารามิเตอร์ที่ระบุความต้องการบางอย่าง จากนั้นคุณสามารถสร้างคอมไพเลอร์ "ระดับที่สูงขึ้น" ที่เรียกใช้ตัวสร้างโค้ดของคุณจากนั้นฟีดที่สร้างรหัสลงในคอมไพเลอร์ภาษาที่จำเป็นโดยอัตโนมัติ
ขั้นตอนที่สอง - แทนที่จะสร้างซอร์สโค้ดแบบข้อความคุณสร้างแผนผังไวยากรณ์นามธรรมที่พิมพ์ขึ้นอย่างรุนแรง คอมไพเลอร์ภาษาบังคับของคุณจะถูกดูดเข้าไปในคอมไพเลอร์ "ระดับที่สูงขึ้น" ของคุณและยอมรับ AST โดยตรงเป็นซอร์สโค้ด นี่ใกล้มากกับสิ่งที่ Haskell ทำ
แม้ว่าจะยังคงอึดอัดใจ ตัวอย่างเช่นคุณมีฟังก์ชั่นที่แตกต่างกันสองประเภท - ฟังก์ชั่นที่ได้รับการประเมินในระหว่างขั้นตอนการสร้างโค้ดและที่ถูกเรียกใช้งานเมื่อโปรแกรมที่สร้างขึ้นถูกรัน มันเหมือนกับความแตกต่างระหว่างฟังก์ชั่นและเทมเพลตใน C ++
ดังนั้นสำหรับเฟส 3 ให้ทำสองอย่างเดียวกัน - ฟังก์ชันเดียวกันกับไวยากรณ์เดียวกันอาจถูกประเมินบางส่วนระหว่าง "การสร้างรหัส" หรือประเมินอย่างสมบูรณ์หรือไม่ได้รับการประเมินเลย นอกจากนี้ให้ยกเลิกการสร้างโหนด AST ที่วนลูปทั้งหมดเพื่อสนับสนุนการเรียกซ้ำ ในความเป็นจริงทิ้งความคิดของโหนด AST เป็นข้อมูลชนิดพิเศษทั้งหมด - ไม่มีโหนด AST "ตามตัวอักษร" เพียงแค่มีค่า ฯลฯ
นี่เป็นสิ่งที่ IO monad ทำได้ - ตัวดำเนินการเชื่อมโยงเป็นวิธีในการเขียน "การกระทำ" เพื่อสร้างโปรแกรม มันไม่มีอะไรพิเศษ - แค่ฟังก์ชั่น นิพจน์และฟังก์ชันจำนวนมากสามารถประเมินได้ในช่วง "การสร้างโค้ด" แต่สิ่งที่ขึ้นอยู่กับผลข้างเคียงของ I / O จะต้องมีการประเมินผลล่าช้าจนกว่าจะถึงเวลารันไทม์ - ไม่ใช่โดยกฎพิเศษใด ๆ การแสดงออก
โดยทั่วไปแล้ว Monads เป็นเพียงการวางนัยทั่วไป - พวกมันมีอินเตอร์เฟสที่เหมือนกัน แต่ใช้การดำเนินการเชิงนามธรรมแตกต่างกันดังนั้นแทนที่จะประเมินคำอธิบายของรหัสที่จำเป็นพวกเขาประเมินสิ่งอื่นแทน การมีอินเทอร์เฟซเดียวกันหมายความว่ามีบางสิ่งที่คุณสามารถทำกับ monads ได้โดยไม่ต้องสนใจ monad ซึ่งกลายเป็นประโยชน์
คำอธิบายนี้จะทำให้นักปราชญ์ระเบิดอย่างไม่ต้องสงสัย แต่สำหรับฉันแล้วมันอธิบายเหตุผลบางประการที่ทำให้ Haskell น่าสนใจ มันพร่าเลือนขอบเขตระหว่างการเขียนโปรแกรมและ metaprogramming และใช้เครื่องมือของฟังก์ชั่นการเขียนโปรแกรมเพื่อบูรณาการการเขียนโปรแกรมที่จำเป็นโดยไม่จำเป็นต้องใช้ไวยากรณ์พิเศษ
คำติชมที่ฉันมีของแม่แบบ C ++ คือพวกเขาเป็นภาษาย่อยที่ใช้งานได้จริงในภาษาที่จำเป็น - เพื่อประเมินฟังก์ชั่นพื้นฐานเดียวกันในการคอมไพล์เวลาแทนที่จะใช้เวลาคุณต้องใช้มันใหม่ในสไตล์ที่แตกต่างอย่างสิ้นเชิง ของการเข้ารหัส ใน Haskell ในขณะที่สิ่งเจือปนจะต้องมีการระบุไว้เช่นนี้ในประเภทของมันฟังก์ชันเดียวกันที่แน่นอนอาจถูกประเมินทั้งในแง่ของการเขียนโปรแกรมเมตาและในความรู้สึกในการรันไทม์ที่ไม่ใช่เมตาโปรแกรมในโปรแกรมเดียวกัน - ไม่มีเส้นแข็ง ระหว่างการเขียนโปรแกรมและ metaprogramming
ที่กล่าวว่ามีบาง metaprogramming สิ่งที่มาตรฐาน Haskell ไม่สามารถทำได้โดยทั่วไปเพราะประเภท (และอาจจะเป็นสิ่งอื่น ๆ ) ไม่ได้เป็นค่าชั้นหนึ่ง มีตัวแปรภาษาที่พยายามแก้ไขปัญหานี้อยู่
หลายสิ่งที่ฉันได้พูดเกี่ยวกับ Haskell สามารถนำไปใช้ในภาษาที่ใช้งานไม่ได้ - และบางครั้งแม้แต่ภาษาที่จำเป็น Haskell นั้นแตกต่างกันเพราะคุณไม่มีทางเลือกนอกจากใช้วิธีนี้ - โดยพื้นฐานแล้วมันบังคับให้คุณเรียนรู้วิธีการทำงานแบบนี้ คุณสามารถ "เขียน C เป็น ML" แต่คุณไม่สามารถ "เขียน C ใน Haskell" - อย่างน้อยก็ไม่ได้โดยไม่ต้องเรียนรู้ว่าเกิดอะไรขึ้นภายใต้ประทุน