ผมทำงานเกี่ยวกับคอมไพเลอร์แคลคูลัสแลมบ์ดาขนาดเล็กที่มีการทำงาน Hindley-มิลเนอร์ระบบอนุมานชนิดและตอนนี้ยังสนับสนุนการปล่อย recursive ของ (ไม่อยู่ในรหัสที่เชื่อมโยง) ซึ่งผมเข้าใจว่าควรจะเพียงพอที่จะทำให้มันสมบูรณ์ทัวริง
ปัญหาคือตอนนี้ฉันไม่รู้ว่าจะสนับสนุนรายการหรือไม่ว่าจะสนับสนุนพวกเขาแล้วและฉันก็ต้องหาวิธีการเข้ารหัสพวกเขา ฉันต้องการที่จะสามารถกำหนดได้โดยไม่ต้องเพิ่มกฎใหม่ในระบบประเภท
วิธีที่ง่ายที่สุดที่ฉันสามารถนึกถึงรายการx
คือเป็นสิ่งที่เป็นnull
(หรือรายการที่ว่างเปล่า) หรือคู่ที่มีทั้งx
รายการx
และ แต่การทำเช่นนี้ฉันต้องสามารถกำหนดคู่และหรือของซึ่งฉันเชื่อว่าเป็นผลิตภัณฑ์และประเภทผลรวม
ดูเหมือนว่าฉันสามารถกำหนดคู่ด้วยวิธีนี้:
pair = λabf.fab
first = λp.p(λab.a)
second = λp.p(λab.b)
เนื่องจากpair
จะมีคนประเภทที่a -> (b -> ((a -> (b -> x)) -> x))
หลังจากผ่านการพูดเป็นint
และstring
ก็ต้องการให้ผลอะไรกับชนิด(int -> (string -> x)) -> x
ซึ่งจะเป็นตัวแทนของคู่ที่และint
string
สิ่งที่รบกวนจิตใจฉันอยู่ที่นี่คือถ้านั่นหมายถึงคู่ทำไมมันไม่สมเหตุสมผลเชิงเหตุผลหรือไม่บอกเป็นนัย ๆint and string
? อย่างไรก็ตามเทียบเท่ากับ(((int and string) -> x) -> x)
ราวกับว่าฉันสามารถมีชนิดผลิตภัณฑ์เป็นพารามิเตอร์ของฟังก์ชันเท่านั้น คำตอบนี้ดูเหมือนจะแก้ไขปัญหานี้ได้ แต่ฉันไม่รู้ว่าสัญลักษณ์ที่เขาใช้หมายถึงอะไร นอกจากนี้หากสิ่งนี้ไม่ได้เข้ารหัสประเภทผลิตภัณฑ์จริง ๆ ฉันสามารถทำอะไรกับประเภทผลิตภัณฑ์ที่ฉันไม่สามารถทำได้ด้วยคำจำกัดความของคู่ด้านบน (พิจารณาว่าฉันสามารถกำหนด n-tuples ด้วยวิธีเดียวกันได้) ถ้าไม่เช่นนั้นจะไม่ขัดแย้งกับความจริงที่ว่าคุณไม่สามารถแสดงร่วม (AFAIK) โดยใช้นัยเพียงอย่างเดียวได้หรือไม่
นอกจากนี้ประเภทผลรวมเป็นอย่างไร ฉันสามารถเข้ารหัสโดยใช้ฟังก์ชันประเภทได้หรือไม่? ถ้าเป็นเช่นนี้จะเพียงพอที่จะกำหนดรายการ? มิฉะนั้นจะมีวิธีอื่นในการกำหนดรายการโดยไม่ต้องขยายระบบประเภทของฉันหรือไม่? และถ้าไม่ฉันจะต้องทำการเปลี่ยนแปลงอะไรถ้าฉันต้องการให้มันง่ายที่สุดเท่าที่จะทำได้?
โปรดจำไว้ว่าฉันเป็นนักเขียนโปรแกรมคอมพิวเตอร์ แต่ไม่ใช่นักวิทยาศาสตร์คอมพิวเตอร์หรือนักคณิตศาสตร์และไม่ดีนักในการอ่านสัญลักษณ์ทางคณิตศาสตร์
แก้ไข: ฉันไม่แน่ใจว่าชื่อทางเทคนิคของสิ่งที่ฉันได้ดำเนินการจนถึงขณะนี้ แต่ทั้งหมดที่ฉันมีคือรหัสที่ฉันเชื่อมโยงด้านบนซึ่งเป็นอัลกอริทึมการสร้างข้อ จำกัด ที่ใช้กฎสำหรับแอปพลิเคชันนามธรรมและตัวแปร จากอัลกอริทึม Hinley-Milner และอัลกอริทึมการรวมที่ได้รับประเภทหลัก ตัวอย่างเช่นการแสดงออก\a.a
จะให้ผลประเภทa -> a
และการแสดงออก\a.(a a)
จะโยนข้อผิดพลาดการตรวจสอบที่เกิดขึ้น ด้านบนของสิ่งนี้ไม่มีlet
กฎที่แน่นอนแต่ฟังก์ชั่นที่ดูเหมือนว่าจะมีผลกระทบเหมือนกันที่ช่วยให้คุณกำหนดฟังก์ชั่นส่วนกลางซ้ำเช่นรหัสหลอกนี้:
GetTypeOfGlobalFunction(term, globalScope, nameOfFunction)
{
// Here 'globalScope' contains a list of name-value pair where every value is of class 'ClosedType',
// meaning their type will be cloned before unified in the unification algorithm so that they can be used polymorphically
tempType = new TypeVariable() // Assign a dummy type to `tempType`, say, type 'x'.
// The next line creates an scope with everything in 'globalScope' plus the 'nameOfFunction = tempType' name-value pair
tempScope = new Scope(globalScope, nameOfFunction, tempType)
type = TypeOfTerm(term, tempScope) // Calculate the type of the term
Unify(tempType, type)
return type
// After returning, the code outside will create a 'ClosedType' using the returned type and add it to the global scope.
}
โดยทั่วไปโค้ดจะรับชนิดของคำตามปกติ แต่ก่อนที่จะรวมมันจะเพิ่มชื่อของฟังก์ชันที่ถูกกำหนดด้วยประเภทดัมมี่ลงในขอบเขตประเภทเพื่อให้สามารถใช้จากภายในตัวเองซ้ำ ๆ
แก้ไข 2:ฉันเพิ่งรู้ว่าฉันต้องการประเภทเรียกซ้ำซึ่งฉันไม่มีเพื่อกำหนดรายการเหมือนที่ฉันต้องการ
let func = \x -> (func x)
) คุณจะได้สิ่งที่ฉันมี