ฉันจะเข้าใจกฎ Hindley-Milner ได้อย่างไร
Hindley-Milner เป็นชุดของกฎในรูปแบบของแคลคูลัสตามลำดับ (ไม่ใช่การหักตามธรรมชาติ) ที่แสดงให้เห็นว่าเราสามารถอนุมานประเภท (ทั่วไป) ของโปรแกรมจากการสร้างโปรแกรมโดยไม่ต้องมีการประกาศอย่างชัดเจน
สัญลักษณ์และสัญลักษณ์
อันดับแรกให้อธิบายสัญลักษณ์และหารือเกี่ยวกับลำดับความสำคัญของโอเปอเรเตอร์
- 𝑥คือตัวระบุ (อย่างไม่เป็นทางการชื่อตัวแปร)
- :หมายถึงประเภทของ (อย่างไม่เป็นทางการตัวอย่างของหรือ "is-a")
- 𝜎 (sigma) เป็นนิพจน์ที่เป็นตัวแปรหรือฟังก์ชัน
- ดังนั้น𝑥: 𝜎อ่าน " 𝑥 is-a 𝜎 "
- ∈หมายถึง "เป็นองค์ประกอบของ"
- 𝚪 (Gamma) คือสภาพแวดล้อม
- ⊦ (เครื่องหมายยืนยัน) หมายถึงการยืนยัน (หรือพิสูจน์ แต่บริบท "การยืนยัน" อ่านได้ดีขึ้น)
- ⊦Γ 𝑥 : σจึงอ่าน "Γอ้าง𝑥ว่าเป็น-A σ "
- 𝑒เป็นตัวอย่างที่เกิดขึ้นจริง (องค์ประกอบ) ประเภทσ
- 𝜏 (tau) เป็นประเภท: พื้นฐาน, ตัวแปร ( 𝛼 ), ฟังก์ชัน𝜏 → 𝜏 ' , หรือผลิตภัณฑ์𝜏 × 𝜏' (ไม่ได้ใช้ผลิตภัณฑ์ที่นี่)
- 𝜏 → 𝜏 'เป็นประเภทการทำงานที่ 𝜏และ𝜏'เป็นประเภทที่อาจแตกต่างกัน
λ𝑥.𝑒วิธีλ (แลมบ์ดา) เป็นฟังก์ชั่นที่ไม่ระบุชื่อที่ใช้อาร์กิวเมนต์𝑥และผลตอบแทนการแสดงออก, 𝑒
ให้ 𝑥 = 𝑒₀ ใน 𝑒₁วิธีการในการแสดงออก𝑒₁แทน𝑒₀ใดก็ตามที่𝑥ปรากฏ
⊑หมายถึงองค์ประกอบก่อนหน้าเป็นประเภทย่อย (ทางการ - คลาสย่อย) ขององค์ประกอบหลัง
- 𝛼เป็นตัวแปรชนิด
- ∀ 𝛼.𝜎เป็นชนิดตัวแปรอาร์กิวเมนต์∀ (สำหรับทั้งหมด), 𝛼 , ส่งคืน𝜎นิพจน์
- ∉ free (𝚪)หมายถึงไม่ได้เป็นองค์ประกอบของตัวแปรประเภทอิสระของ 𝚪 ที่กำหนดไว้ในบริบทด้านนอก (ตัวแปรที่ถูกผูกไว้สามารถทดแทนได้)
ทุกอย่างที่อยู่เหนือเส้นคือหลักฐานทุกอย่างด้านล่างคือข้อสรุป ( Per Martin-Löf )
ลำดับความสำคัญตามตัวอย่าง
ฉันได้นำตัวอย่างที่ซับซ้อนมากขึ้นบางส่วนจากกฎและใส่วงเล็บที่ซ้ำซ้อนที่แสดงความสำคัญกว่า:
- 𝑥: 𝜎 ∈ 𝚪 สามารถเขียนได้(𝑥: 𝜎) ∈ 𝚪
Γ⊦ 𝑥 : σสามารถเขียนΓ⊦ ( 𝑥 : σ )
⊦⊦ ให้ 𝑥 = 𝑒₀ ใน 𝑒₁ : 𝜏
เทียบเท่ากัน 𝚪 ⊦ (( อนุญาต ( 𝑥 = 𝑒₀ ) ใน 𝑒₁ ): 𝜏 )
𝚪 ⊦ 𝜆𝑥.𝑒 : 𝜏 → 𝜏 'เทียบเท่ากัน 𝚪 ⊦ (( 𝜆𝑥.𝑒 ): ( 𝜏 → 𝜏' ))
จากนั้นช่องว่างขนาดใหญ่ที่แยกคำแถลงยืนยันและเงื่อนไขอื่น ๆ ระบุชุดของเงื่อนไขเบื้องต้นและในที่สุดเส้นแนวนอนที่แยกหลักฐานจากข้อสรุปนำมาซึ่งจุดสิ้นสุดของลำดับความสำคัญ
กฎระเบียบ
สิ่งที่ตามมาที่นี่คือการตีความกฎภาษาอังกฤษแต่ละข้อตามด้วยการพูดซ้ำอย่างหลวม ๆ และคำอธิบาย
ตัวแปร
รับ𝑥เป็นประเภทของ 𝜎 (sigma), องค์ประกอบของ 𝚪 (แกมมา),
สรุป 𝚪 ยืนยัน𝑥คือ 𝜎
ใส่อีกวิธีหนึ่งใน 𝚪 เรารู้ว่า𝑥เป็นประเภท 𝜎 เพราะ𝑥เป็นประเภท 𝜎 ใน 𝚪
นี่คือพื้นซ้ำซาก ชื่อตัวระบุเป็นตัวแปรหรือฟังก์ชั่น
ฟังก์ชั่นการใช้งาน
กำหนด 𝚪 asserts 𝑒₀เป็นประเภทการใช้งานและ 𝚪 asserts 𝑒₁คือ 𝜏
สรุป 𝚪 ยืนยันการใช้ฟังก์ชัน𝑒₀ถึง𝑒₁เป็นประเภท 𝜏 '
ในการย้ำกฎเรารู้ว่าฟังก์ชั่นการใช้งานส่งคืนประเภท type 'เพราะฟังก์ชั่นมีประเภท 𝜏 → 𝜏' และได้รับการโต้แย้งประเภท 𝜏
นี่หมายความว่าถ้าเรารู้ว่าฟังก์ชั่นคืนค่าประเภทและเรานำไปใช้กับการโต้แย้งผลที่ได้จะเป็นตัวอย่างของประเภทที่เรารู้ว่ามันส่งกลับ
ฟังก์ชั่นนามธรรม
รับ 𝚪 และ𝑥ของประเภท 𝜏 asserts 𝑒เป็นประเภท conclud '
สรุป 𝚪 ยืนยันฟังก์ชั่นที่ไม่ระบุชื่อ 𝜆 ของ𝑥การแสดงออกกลับ𝑒เป็นประเภท 𝜏 → 𝜏'
อีกครั้งเมื่อเราเห็นฟังก์ชั่นที่รับ𝑥และส่งคืนนิพจน์𝑒เรารู้ว่ามันเป็นประเภท 𝜏 → 𝜏 'เพราะ𝑥 (a 𝜏) ยืนยันว่า𝑒คือ 𝜏'
หากเรารู้ว่า𝑥เป็นประเภท 𝜏 ดังนั้นนิพจน์𝑒เป็นประเภท 𝜏 'ดังนั้นฟังก์ชันของ𝑥นิพจน์ที่กลับมา𝑒เป็นประเภท𝑒→ 𝜏'
ขอประกาศตัวแปร
รับ 𝚪 asserts 𝑒₀, ของประเภท 𝜎, และ 𝚪 และ𝑥, ของประเภท 𝜎, asserts 𝑒₁ของประเภท 𝜏
สรุป 𝚪 asserts let
𝑥 = in
𝑒₀𝑒₁ของประเภท 𝜏
อย่างหลวม ๆ bound ถูกผูกไว้กับ𝑒₀ in 𝑒₁ (a 𝜏) เพราะ𝑒₀คือ 𝜎 และ𝑥เป็น 𝜎 ที่อ้างว่า𝑒₁คือ 𝜏
นี่หมายความว่าถ้าเรามีนิพจน์𝑒₀นั่นคือ 𝜎 (เป็นตัวแปรหรือฟังก์ชั่น) และชื่อบางชื่อ𝑥, ยัง 𝜎 และการแสดงออกของ 𝜏 ประเภท 𝜏 แล้วเราสามารถแทนที่𝑒₀สำหรับ𝑥ทุกที่ที่ปรากฏภายใน ของ𝑒₁
instantiation
รับ 𝚪 asserts 𝑒ของ type 𝜎 'และ 𝜎' เป็น subtype ของ 𝜎
summe 𝚪 asserts 𝑒เป็น type 𝜎
การแสดงออก𝑒เป็นประเภทผู้ปกครอง 𝜎 เพราะการแสดงออก𝑒เป็นประเภทย่อย 𝜎 'และ 𝜎 เป็นประเภทผู้ปกครองของ 𝜎'
หากอินสแตนซ์เป็นประเภทที่เป็นประเภทย่อยของประเภทอื่นแล้วมันก็เป็นอินสแตนซ์ของประเภทซุปเปอร์ที่ - ประเภททั่วไปมากขึ้น
ลักษณะทั่วไป
รับ 𝚪 asserts 𝑒คือ 𝜎 และ 𝛼 ไม่ได้เป็นองค์ประกอบของตัวแปรอิสระของ 𝚪,
สรุป 𝚪 asserts type, พิมพ์สำหรับนิพจน์อาร์กิวเมนต์ทั้งหมด 𝛼 คืนค่า 𝜎 expression
ดังนั้นโดยทั่วไป𝑒ถูกพิมพ์ 𝜎 สำหรับตัวแปรอาร์กิวเมนต์ทั้งหมด (𝛼) ที่ส่งคืน because เพราะเรารู้ว่า𝑒คือ 𝜎 และ 𝛼 ไม่ใช่ตัวแปรอิสระ
ซึ่งหมายความว่าเราสามารถทำให้โปรแกรมทั่วไปยอมรับทุกประเภทสำหรับข้อโต้แย้งที่ไม่ได้ถูกผูกไว้ในขอบเขตที่มีอยู่ (ตัวแปรที่ไม่ใช่ของท้องถิ่น) ตัวแปรที่ผูกไว้เหล่านี้สามารถทดแทนได้
วางมันทั้งหมดเข้าด้วยกัน
ด้วยสมมติฐานบางประการ (เช่นไม่มีตัวแปรอิสระ / ไม่ได้กำหนดสภาวะแวดล้อมที่รู้จัก) เรารู้ประเภทของ:
- องค์ประกอบอะตอมของโปรแกรมของเรา (ตัวแปร)
- ค่าที่ส่งคืนโดยฟังก์ชั่น (Function Application)
- ฟังก์ชั่นสร้าง (ฟังก์ชั่นนามธรรม),
- let bindings (ให้ประกาศตัวแปร)
- ประเภทหลักของอินสแตนซ์ (การสร้างอินสแตนซ์) และ
- นิพจน์ทั้งหมด (ทั่วไป)
ข้อสรุป
กฎเหล่านี้รวมกันทำให้เราสามารถพิสูจน์ประเภททั่วไปของโปรแกรมที่ถูกยืนยันได้โดยไม่ต้องมีคำอธิบายประกอบประเภท