คำตอบนี้เป็นการตอบสนองต่อปัญหาที่นำโดย illissius จุดต่อจุด:
- มันน่าเกลียดที่จะใช้ $ (fooBar '' Asdf) แค่ดูไม่ดี ผิวเผินแน่นอน แต่มันมีส่วนช่วย
ฉันเห็นด้วย. ฉันรู้สึกว่า $ () ได้รับเลือกให้ดูเหมือนเป็นส่วนหนึ่งของภาษาโดยใช้พาเลทสัญลักษณ์ที่คุ้นเคยของ Haskell อย่างไรก็ตามนั่นคือสิ่งที่คุณ / ไม่ / ต้องการในสัญลักษณ์ที่ใช้สำหรับการประกบแมโครของคุณ พวกเขาผสมผสานกันมากเกินไปและแง่มุมด้านเครื่องสำอางนี้ค่อนข้างสำคัญ ฉันชอบรูปลักษณ์ของ {{}} สำหรับรอยต่อเพราะมันค่อนข้างชัดเจน
- แม้แต่ผู้เขียนที่น่าเกลียดก็ยังเขียน บางครั้งการอ้างถึงใช้งานได้ แต่หลายครั้งที่คุณต้องทำ AST การรับสินบนและการประปาด้วยตนเอง [API] [1] มีขนาดใหญ่และเทอะทะมีหลายกรณีที่คุณไม่สนใจ แต่ยังคงต้องส่งและกรณีที่คุณสนใจมักจะปรากฏในรูปแบบที่คล้ายกัน แต่ไม่เหมือนกันหลายรูปแบบ (ข้อมูล เทียบกับ newtype, style-record เทียบกับ constructor ปกติและอื่น ๆ ) มันน่าเบื่อและซ้ำซากในการเขียนและซับซ้อนพอที่จะไม่ใช้กลไก [ข้อเสนอการปฏิรูป] [2] กล่าวถึงเรื่องนี้บางส่วน
ฉันยังเห็นด้วยกับเรื่องนี้อย่างไรก็ตามในขณะที่ความคิดเห็นบางส่วนใน "ทิศทางใหม่สำหรับ TH" สังเกตว่าการขาดการอ้างอิง AST ที่ดีนอกกรอบไม่ใช่ข้อบกพร่องที่สำคัญ ในแพคเกจ WIP นี้ผมพยายามที่จะแก้ไขปัญหาเหล่านี้ในรูปแบบห้องสมุด: https://github.com/mgsloan/quasi-extras จนถึงตอนนี้ฉันอนุญาตให้ประกบกันในสถานที่ไม่กี่แห่งมากกว่าปกติและสามารถจับคู่รูปแบบกับ AST ได้
- การ จำกัด เวทีคือนรก การไม่สามารถประกบฟังก์ชั่นที่กำหนดไว้ในโมดูลเดียวกันนั้นเป็นส่วนเล็ก ๆ ของมัน: ผลที่ตามมาคือถ้าคุณมีการต่อรอยระดับบนสุดทุกอย่างหลังจากมันในโมดูลจะอยู่นอกขอบเขตของสิ่งใด ๆ ก่อนหน้านี้ ภาษาอื่นที่มีคุณสมบัตินี้ (C, C ++) ทำให้มันใช้งานได้โดยอนุญาตให้คุณส่งต่อสิ่งที่ประกาศ แต่ Haskell ไม่ได้ หากคุณต้องการการอ้างอิงแบบวนซ้ำระหว่างการประกาศแบบต่อเชื่อมหรือการอ้างอิงและการพึ่งพาของพวกเขาคุณมักจะเมา
ฉันเคยพบปัญหานิยามคำนิยาม TH ที่เป็นไปไม่ได้มาก่อน ... มันค่อนข้างน่ารำคาญ มีวิธีแก้ปัญหา แต่มันน่าเกลียด - ห่อสิ่งที่เกี่ยวข้องในการพึ่งพาวงจรในการแสดงออก TH ที่รวมการประกาศทั้งหมดที่สร้างขึ้น หนึ่งในเครื่องกำเนิดไฟฟ้าที่ประกาศเหล่านี้อาจเป็นเสมือน quer-quoter ที่ยอมรับรหัส Haskell
- มันไม่มีหลักการ สิ่งที่ฉันหมายถึงคือเวลาส่วนใหญ่เมื่อคุณแสดงสิ่งที่เป็นนามธรรมมีหลักการหรือแนวคิดบางอย่างที่อยู่เบื้องหลังสิ่งที่เป็นนามธรรม สำหรับหลาย abstractions หลักการเบื้องหลังพวกเขาสามารถแสดงในประเภทของพวกเขา เมื่อคุณกำหนดคลาสประเภทคุณมักจะสามารถกำหนดกฎหมายซึ่งอินสแตนซ์ที่ควรเชื่อฟังและลูกค้าสามารถสมมติได้ หากคุณใช้ [คุณสมบัติทั่วไปใหม่ของ GHC] [3] เพื่อสรุปรูปแบบของการประกาศอินสแตนซ์ในประเภทข้อมูลใด ๆ (ภายในขอบเขต) คุณจะต้องพูดว่า "สำหรับประเภทผลรวมมันใช้งานได้เช่นนี้สำหรับประเภทผลิตภัณฑ์มันทำงานเช่นนั้น " แต่เทมเพลตแฮสเคลล์เป็นเพียงมาโครที่โง่ ไม่ใช่สิ่งที่เป็นนามธรรมในระดับความคิด แต่สิ่งที่เป็นนามธรรมในระดับของ AST ซึ่งดีกว่า แต่มีเพียงพอประมาณเท่านั้นกว่าสิ่งที่เป็นนามธรรมในระดับของข้อความล้วน
มันไร้ศีลธรรมก็ต่อเมื่อคุณทำสิ่งที่ไร้ศีลธรรมกับมัน ข้อแตกต่างเพียงอย่างเดียวคือเมื่อคอมไพเลอร์ใช้กลไกสำหรับนามธรรมคุณมีความมั่นใจมากขึ้นว่านามธรรมไม่รั่วไหล บางทีการออกแบบภาษาที่เป็นประชาธิปไตยอาจฟังดูน่ากลัว! ผู้สร้างห้องสมุด TH ต้องจัดทำเอกสารอย่างดีและชัดเจนกำหนดความหมายและผลลัพธ์ของเครื่องมือที่พวกเขามีให้ ตัวอย่างที่ดีของหลักการ TH คือแพ็กเกจที่ได้รับ: http://hackage.haskell.org/package/derive - มันใช้ DSL เพื่อเป็นตัวอย่างของการพิสูจน์ / ระบุ / การสืบทอดที่แท้จริง
- มันเชื่อมโยงคุณกับ GHC ในทางทฤษฎีผู้รวบรวมรายอื่นสามารถใช้งานได้ แต่ในทางปฏิบัติฉันสงสัยว่าสิ่งนี้จะเกิดขึ้นได้ (นี่เป็นสิ่งที่ตรงกันข้ามกับส่วนขยายระบบประเภทต่าง ๆ ซึ่งแม้ว่า GHC จะสามารถนำไปใช้งานได้ในขณะนี้ แต่ฉันสามารถจินตนาการได้ว่าจะมีการนำคอมไพเลอร์อื่นมาใช้บนถนนและเป็นมาตรฐานในที่สุด)
นั่นเป็นจุดที่ดีทีเดียว - TH API นั้นค่อนข้างใหญ่และน่าเบื่อ การใช้งานซ้ำอีกครั้งดูเหมือนว่าอาจจะยาก อย่างไรก็ตามมีเพียงไม่กี่วิธีเท่านั้นในการแบ่งปัญหาของการเป็นตัวแทนของ Haskell AST ฉันจินตนาการว่าการคัดลอก TH ADT และการเขียนตัวแปลงไปยังการเป็นตัวแทน AST ภายในจะทำให้คุณได้รับประโยชน์อย่างมาก นี่จะเทียบเท่ากับความพยายาม (ไม่สำคัญ) ในการสร้าง Haskell-src-meta นอกจากนี้ยังสามารถนำมาใช้ใหม่ได้ง่ายๆโดยการพิมพ์ TH AST และการใช้เครื่องมือแยกวิเคราะห์ภายในของคอมไพเลอร์
ในขณะที่ฉันอาจจะผิดฉันไม่เห็นว่า TH เป็นส่วนขยายที่ซับซ้อนของคอมไพเลอร์จากมุมมองการใช้งาน นี่คือหนึ่งในประโยชน์ของการ "ทำให้มันง่าย" และไม่มีชั้นพื้นฐานที่น่าดึงดูดในเชิงทฤษฎี
- API ไม่เสถียร เมื่อเพิ่มฟีเจอร์ภาษาใหม่ลงใน GHC และแพคเกจ template-haskell ได้รับการอัปเดตเพื่อรองรับคุณสมบัติเหล่านี้มักจะเกี่ยวข้องกับการเปลี่ยนแปลงที่ไม่เข้ากันกับส่วนหลังของประเภทข้อมูล TH หากคุณต้องการให้รหัส TH ของคุณสามารถทำงานร่วมกับ GHC ได้มากกว่าหนึ่งรุ่นคุณจะต้องระมัดระวังและใช้งาน
CPP
ได้
นี่เป็นจุดที่ดี แต่ค่อนข้างน่าสนใจ ในขณะที่มีการเพิ่ม API เมื่อเร็ว ๆ นี้พวกเขายังไม่ได้รับความเสียหายอย่างกว้างขวาง นอกจากนี้ฉันคิดว่าด้วยการอ้างอิง AST ที่เหนือกว่าที่ฉันกล่าวถึงก่อนหน้านี้ API ที่จำเป็นต้องใช้จริงนั้นสามารถลดลงได้อย่างมาก หากไม่มีสิ่งก่อสร้าง / การจับคู่ที่ต้องการฟังก์ชั่นที่แตกต่างกันและจะแสดงเป็นตัวอักษรแทน API ส่วนใหญ่จะหายไป ยิ่งไปกว่านั้นรหัสที่คุณเขียนจะทำให้พอร์ตง่ายขึ้นสำหรับการเป็นตัวแทน AST สำหรับภาษาที่คล้ายกับ Haskell
โดยสรุปแล้วฉันคิดว่า TH เป็นเครื่องมือที่ทรงพลังและไม่ได้รับความสนใจ ความเกลียดชังที่น้อยลงอาจนำไปสู่ระบบนิเวศที่มีชีวิตชีวามากขึ้นของห้องสมุดสนับสนุนการใช้ต้นแบบคุณลักษณะภาษาเพิ่มเติม มีการตั้งข้อสังเกตว่า TH เป็นเครื่องมือที่มีอำนาจเหนือกว่าที่สามารถให้คุณ / ทำ / เกือบทุกอย่าง โกลาหล! ฉันคิดว่าพลังนี้ช่วยให้คุณสามารถเอาชนะข้อ จำกัด ส่วนใหญ่และสร้างระบบที่สามารถใช้วิธีการเขียนโปรแกรมเมตาค่อนข้างดี มันคุ้มค่ากับการใช้แฮ็กที่น่าเกลียดเพื่อจำลองการใช้งาน "เหมาะสม" เนื่องจากวิธีนี้การออกแบบการใช้งาน "เหมาะสม" จะค่อยๆชัดเจนขึ้น
ในนิพพานในอุดมคติส่วนตัวของฉันภาษาส่วนใหญ่จะย้ายออกจากคอมไพเลอร์ไปสู่ห้องสมุดของความหลากหลายเหล่านี้ ความจริงที่ว่าคุณลักษณะถูกนำมาใช้เนื่องจากห้องสมุดไม่ได้มีอิทธิพลอย่างมากต่อความสามารถในการสรุปอย่างซื่อสัตย์
Haskell คือคำตอบทั่วไปสำหรับรหัส boilerplate? สิ่งที่เป็นนามธรรม สิ่งที่เราชื่นชอบคืออะไร? ฟังก์ชั่นและพิมพ์ดีด!
Typeclasses ให้เรากำหนดชุดของเมธอดที่สามารถใช้ในฟังก์ชันทั่วไปในคลาสนั้น อย่างไรก็ตามนอกเหนือจากนี้วิธีเดียวที่จะช่วยให้คลาสหลีกเลี่ยงการสร้างแผ่นข้อมูลด้วยการเสนอ "คำจำกัดความเริ่มต้น" ตอนนี้นี่เป็นตัวอย่างของคุณสมบัติที่ไม่มีหลักการ!
ชุดการรวมที่น้อยที่สุดไม่สามารถประกาศได้ / คอมไพเลอร์สามารถตรวจสอบได้ สิ่งนี้อาจนำไปสู่คำจำกัดความที่ไม่ตั้งใจซึ่งให้ผลด้านล่างเนื่องจากการเรียกซ้ำซึ่งกันและกัน
แม้จะมีความสะดวกสบายมากและอำนาจนี้จะให้ผลผลิตคุณไม่สามารถระบุค่าเริ่มต้น superclass เนื่องจากกรณีเด็กกำพร้า http://lukepalmer.wordpress.com/2009/01/25/a-world-without-orphans/ เหล่านี้จะช่วยให้เราแก้ไข ลำดับชั้นตัวเลขอย่างงดงาม!
ไปหลังจาก TH-เช่นความสามารถในการเป็นค่าเริ่มต้นนำไปสู่วิธีการhttp://www.haskell.org/haskellwiki/GHC.Generics ในขณะที่นี่คือสิ่งที่ดีประสบการณ์เดียวของฉันการแก้จุดบกพร่องรหัสโดยใช้ข้อมูลทั่วไปเหล่านี้เป็นไปไม่ได้เนื่องจากขนาดของประเภทที่ชักนำและ ADT มีความซับซ้อนเช่นเดียวกับ AST https://github.com/mgsloan/th-extra/commit/d7784d95d396eb3abdb409a24360beb03731c88c
กล่าวอีกนัยหนึ่งสิ่งนี้เกิดขึ้นหลังจากคุณสมบัติที่ให้บริการโดย TH แต่ต้องยกทั้งโดเมนของภาษาภาษาที่ใช้ในการสร้างลงในการแสดงระบบชนิด ในขณะที่ฉันเห็นว่ามันทำงานได้ดีสำหรับปัญหาทั่วไปของคุณสำหรับคนที่ซับซ้อน แต่ดูเหมือนว่าจะมีสัญลักษณ์กองที่น่ากลัวยิ่งกว่าแฮกเกอร์ TH
TH ให้การคำนวณเวลาส่งออกมูลค่าระดับของรหัสผลลัพธ์ในขณะที่ generics บังคับให้คุณยกส่วนการจับคู่รูปแบบ / การเรียกซ้ำของรหัสลงในระบบประเภท แม้ว่าสิ่งนี้จะ จำกัด ผู้ใช้ด้วยวิธีที่ค่อนข้างมีประโยชน์ แต่ฉันไม่คิดว่าความซับซ้อนนั้นคุ้มค่า
ฉันคิดว่าการปฏิเสธของ TH และ metaprogramming ที่เหมือนเสียงกระเพื่อมนำไปสู่การตั้งค่าต่อสิ่งต่าง ๆ เช่นค่าเริ่มต้นของวิธีการแทนการยืดหยุ่นมากขึ้นการขยายตัวของแมโครเหมือนกับการประกาศของอินสแตนซ์ วินัยในการหลีกเลี่ยงสิ่งต่าง ๆ ที่อาจนำไปสู่ผลลัพธ์ที่ไม่ดีนั้นเป็นสิ่งที่ฉลาดอย่างไรก็ตามเราไม่ควรมองข้ามว่าระบบประเภทที่มีความสามารถของ Haskell ช่วยให้การเปรียบเทียบโปรแกรมน่าเชื่อถือมากกว่าในสภาพแวดล้อมอื่น ๆ (โดยตรวจสอบรหัสที่สร้างขึ้น)