อะไรคือคำอธิบายสั้น ๆ แต่สมบูรณ์ของระบบประเภท pure / dependent


32

หากบางสิ่งนั้นเรียบง่ายก็ควรอธิบายให้สมบูรณ์ด้วยคำสองสามคำ สิ่งนี้สามารถทำได้สำหรับ calcul-แคลคูลัส:

calcul-แคลคูลัสเป็นไวยากรณ์ไวยากรณ์ (โดยทั่วไปโครงสร้าง) ที่มีกฎการลด (ซึ่งหมายถึงขั้นตอนการค้นหา / แทนที่จะถูกนำไปใช้ซ้ำกับทุกรูปแบบที่เกิดขึ้นเฉพาะจนกว่าจะไม่มีรูปแบบดังกล่าว)

ไวยากรณ์:

Term = (Term Term) | (λ Var . Term) | Var

กฎการลด:

((λ var body) term) -> SUBS(body,var,term)
    where `SUBS` replaces all occurrences of `var`
    by `term` in `body`, avoiding name capture.

ตัวอย่าง:

(λ a . a)                             -> (λ a a)
((λ a . (λ b . (b a))) (λ x . x))     -> (λ b . (b (λ x x)))
((λ a . (a a)) (λ x . x))             -> (λ x . x)
((λ a . (λ b . ((b a) a))) (λ x . x)) -> (λ b . ((b (λ x . x)) (λ x . x)))
((λ x . (x x)) (λ x . (x x)))         -> never halts

ในขณะที่ค่อนข้างไม่เป็นทางการใครจะเถียงว่านี่เป็นข้อมูลที่เพียงพอสำหรับมนุษย์ปกติที่จะเข้าใจ calcul- แคลคูลัสโดยรวม - และใช้เวลา22 บรรทัดของการทำเครื่องหมาย ฉันพยายามที่จะเข้าใจระบบการพิมพ์ที่บริสุทธิ์ / ขึ้นอยู่กับที่ใช้โดย Idris / Agda และโครงการที่คล้ายกัน แต่คำอธิบายที่สั้นกว่าที่ฉันสามารถหาได้คือSimply Easy - กระดาษที่ดี แต่ดูเหมือนว่าจะเข้าใจความรู้ก่อนหน้านี้มากมาย คำจำกัดความ) ที่ฉันไม่มี ฉันคิดว่าบางสิ่งบางอย่างที่อุดมไปด้วยน้อยกว่าสามารถกำจัดอุปสรรคเหล่านั้น ดังนั้น,

เป็นไปได้หรือไม่ที่จะให้คำอธิบายสั้น ๆ โดยสมบูรณ์เกี่ยวกับระบบชนิดบริสุทธิ์ / ขึ้นอยู่กับในรูปแบบเดียวกับที่ฉันนำเสนอ calcul-แคลคูลัสด้านบน?


4
กฎของระบบ Pure Type นั้นสั้นมาก ซิงเกิ้ลอีซี่คือการดำเนินการตามประเภท

2
ดังนั้นมันจึงไม่ใช่ "ศัตรู" ในแง่ของความก้าวร้าว แต่ในแง่ที่คุณคิดว่าฉันเรียกร้องมากเพราะไม่ได้แสดงความพยายามอย่างเพียงพอในการค้นหาคำตอบด้วยตัวเอง? หากเป็นกรณีนี้ฉันเห็นด้วยกับคำถามนี้อาจเรียกร้องมากดังนั้นอาจจะไม่ดี แต่ยังมีความพยายามอีกมากคุณคิดว่าฉันควรแก้ไขในความพยายามของฉันหรือไม่?
MaiaVictor

3
ในนามของผู้เขียนร่วมของฉันซึ่งเป็นคนเขียนข้อความของ "การใช้งานแบบฝึกหัดของแลมบ์ดาแลมบ์ดา" ซึ่งใช้แทนชื่อ "ง่ายง่าย" แทน ฉันเขียนเคอร์เนลของรหัสซึ่งเป็นตัวตรวจสอบชนิดใน <100 บรรทัดของ Haskell

2
จากนั้นฉันก็แสดงออกอย่างไม่ดี ฉันชอบกระดาษ "ง่าย ๆ " และฉันอ่านมันทุกครั้งตั้งแต่ไม่กี่วันที่ผ่านมา - มันเป็นสิ่งเดียวในโลกที่ให้ความรู้สึกบางส่วนแก่ฉันฉันเริ่มเข้าใจเรื่อง (และเชื่อว่าฉันพยายาม) . แต่ฉันคิดว่ามันมุ่งเป้าไปที่สาธารณะที่มีความรู้มากกว่าฉันและนั่นอาจเป็นสาเหตุที่ฉันยังคงมีปัญหาในการรับส่วนหนึ่งของมัน ไม่มีอะไรเกี่ยวข้องกับคุณภาพของกระดาษ แต่เป็นข้อ จำกัด ของฉันเอง
MaiaVictor

1
@pigworker และรหัสเป็นส่วนที่ฉันชอบเพราะมัน (ในส่วนที่เกี่ยวกับคำอธิบายภาษาอังกฤษ) นั้นสั้นกว่ามาก แต่ก็สมบูรณ์คำอธิบายของทั้งหมดตามที่ฉันถามที่นี่ คุณมีสำเนาของรหัสที่ฉันสามารถดาวน์โหลดได้หรือไม่?
MaiaVictor

คำตอบ:


7

คำปฏิเสธ

นี่เป็นเรื่องที่ไม่เป็นทางการตามที่คุณร้องขอ

ไวยากรณ์

ในภาษาที่พิมพ์ขึ้นอยู่กับว่าเรามีเครื่องผูกที่ระดับประเภทเช่นเดียวกับที่ระดับค่า:

Term = * | (∀ (Var : Term). Term) | (Term Term) | (λ Var. Term) | Var

คำที่พิมพ์ได้ดีเป็นคำที่มีประเภทที่แนบมาเราจะเขียนt ∈ σหรือ

σ
t

เพื่อแสดงให้เห็นว่าคำว่ามีประเภทtσ

กฎการพิมพ์

เพื่อความเรียบง่ายเราจำเป็นต้องใช้λ v. t ∈ ∀ (v : σ). τทั้งในλและผูกตัวแปรเดียวกัน (vในกรณีนี้)

กฎ:

t ∈ σ is well-formed if σ ∈ * and t is in normal form (0)

*            ∈ *                                                 (1)
∀ (v : σ). τ ∈ *             -: σ ∈ *, τ ∈ *                     (2)
λ v. t       ∈ ∀ (v : σ). τ  -: t ∈ τ                            (3)
f x          ∈ SUBS(τ, v, x) -: f ∈ ∀ (v : σ). τ, x ∈ σ          (4)
v            ∈ σ             -: v was introduced by ∀ (v : σ). τ (5)

ดังนั้น*คือ "ประเภททุกประเภท" (1), รูปแบบประเภทจากประเภท (2), นามธรรม Lambda มีปี่ชนิด (3) และถ้าvเป็นที่รู้จักโดย∀ (v : σ). τแล้วvมีประเภทσ (5)

"ในรูปแบบปกติ" หมายความว่าเราดำเนินการลดจำนวนมากที่สุดโดยใช้กฎการลด:

กฎการลด "The"

(λ v. b ∈ ∀ (v : σ). τ) (t ∈ σ) ~> SUBS(b, v, t) ∈ SUBS(τ, v, t)
    where `SUBS` replaces all occurrences of `v`
    by `t` in `τ` and `b`, avoiding name capture.

หรือในรูปแบบสองมิติที่

σ
t

หมายถึงt ∈ σ:

(∀ (v : σ). τ) σ    SUBS(τ, v, t)
                 ~>
(λ  v     . b) t    SUBS(b, v, t)

เป็นไปได้ที่จะใช้การลบแลมบ์ดากับคำศัพท์เมื่อคำนั้นมีชนิดเดียวกับตัวแปรในปริมาณทั้งหมดที่เกี่ยวข้อง จากนั้นเราจะลดทั้ง lambda abstraction และ forall quantifier ในลักษณะเดียวกับใน lambda แคลคูลัสบริสุทธิ์ก่อน หลังจากลบส่วนระดับค่าเราจะได้รับ (4) กฎการพิมพ์

ตัวอย่าง

นี่คือตัวดำเนินการแอปพลิเคชันฟังก์ชัน:

∀ (A : *) (B : A -> *) (f : ∀ (y : A). B y) (x : A). B x
λ  A       B            f                    x     . f x

(เราย่อ∀ (x : σ). τไปσ -> τถ้าτไม่ได้พูดถึงx)

fผลตอบแทนB yสำหรับการใด ๆ ที่ให้บริการประเภทy Aเราใช้fไปxซึ่งเป็นประเภทที่เหมาะสมAและใช้แทนyสำหรับxในหลัง.จึง~>f x ∈ SUBS(B y, y, x)f x ∈ B x

ตอนนี้ขอย่อตัวดำเนินการประยุกต์ใช้ฟังก์ชั่นเป็นappและนำไปใช้กับตัวเอง:

∀ (A : *) (B : A -> *). ?
λ  A       B          . app ? ? (app A B)

ฉันวาง?เงื่อนไขที่เราต้องการให้ ก่อนอื่นเราขอแนะนำและยกตัวอย่างอย่างชัดเจนAและB:

∀ (f : ∀ (y : A). B y) (x : A). B x
app A B

ตอนนี้เราต้องรวมสิ่งที่เรามี

∀ (f : ∀ (y : A). B y) (x : A). B x

ซึ่งเหมือนกับ

(∀ (y : A). B y) -> ∀ (x : A). B x

และสิ่งที่app ? ?ได้รับ

∀ (x : A'). B' x

ผลลัพธ์นี้ใน

A' ~ ∀ (y : A). B y
B' ~ λ _. ∀ (x : A). B x -- B' ignores its argument

(ดูที่ predicativity คืออะไร )

การแสดงออกของเรา (หลังจากเปลี่ยนชื่อ) จะกลายเป็น

∀ (A : *) (B : A -> *). ?
λ  A       B          . app (∀ (x : A). B x) (λ _. ∀ (x : A). B x) (app A B)

ตั้งแต่ใด ๆA, Bและf(ที่f ∈ ∀ (y : A). B y)

∀ (y : A). B y
app A B f

เราสามารถยกตัวอย่างAและBรับ (สำหรับfประเภทที่เหมาะสม)

∀ (y : ∀ (x : A). B x). ∀ (x : A). B x
app (∀ (x : A). B x) (λ _. ∀ (x : A). B x) f

(∀ (x : A). B x) -> ∀ (x : A). B xและลายเซ็นชนิดเทียบเท่ากับ

การแสดงออกทั้งหมดคือ

∀ (A : *) (B : A -> *). (∀ (x : A). B x) -> ∀ (x : A). B x
λ  A       B          . app (∀ (x : A). B x) (λ _. ∀ (x : A). B x) (app A B)

กล่าวคือ

∀ (A : *) (B : A -> *) (f : ∀ (x : A). B x) (x : A). B x
λ  A       B            f                    x     .
    app (∀ (x : A). B x) (λ _. ∀ (x : A). B x) (app A B) f x

ซึ่งหลังจากการลดลงทั้งหมดที่ระดับมูลค่าจะให้ผลappตอบแทนเท่าเดิม

ดังนั้นในขณะที่ต้องใช้เพียงไม่กี่ก้าวในแคลคูลัสแลมบ์ดาบริสุทธิ์appจากapp appการตั้งค่า (และโดยเฉพาะอย่างยิ่งการพิมพ์พึ่งพา) เรายังต้องดูแลเกี่ยวกับการรวมกันและสิ่งที่ซับซ้อนมากขึ้นแม้จะมีความสะดวกสบายไม่สอดคล้องกัน ( * ∈ *)

การตรวจสอบประเภท

  • ถ้าtเป็นเช่น*นั้นt ∈ *โดย (1)
  • ถ้าtเป็น∀ (x : σ) τ, σ ∈? *, τ ∈? *(ดูหมายเหตุเกี่ยวกับ∈?ด้านล่าง) แล้วt ∈ *โดย (2)
  • ถ้าtเป็นf x, f ∈ ∀ (v : σ) τสำหรับบางคนσและτ, x ∈? σแล้วt ∈ SUBS(τ, v, x)โดย (4)
  • ถ้าtเป็นตัวแปรv, vได้รับการแนะนำให้รู้จัก∀ (v : σ). τแล้วt ∈ σโดย (5)

สิ่งเหล่านี้ล้วนเป็นกฎการอนุมาน แต่เราไม่สามารถทำแบบเดียวกันกับ lambdas ได้ (การอนุมานประเภทนั้นไม่สามารถอธิบายได้สำหรับประเภทที่ขึ้นต่อกัน) ดังนั้นสำหรับ lambdas เราตรวจสอบ ( t ∈? σ) แทนที่จะอนุมาน:

  • หากtมีการλ v. bและตรวจสอบกับ∀ (v : σ) τ, b ∈? τแล้วt ∈ ∀ (v : σ) τ
  • หากtเป็นอย่างอื่นและตรวจสอบกับσจากนั้นอนุมานประเภทของการtใช้ฟังก์ชั่นด้านบนและตรวจสอบว่ามันเป็นσ

การตรวจสอบความเท่าเทียมกันสำหรับประเภทพวกเขาต้องการที่จะอยู่ในรูปแบบปกติเพื่อที่จะตัดสินใจว่าจะtมีการพิมพ์σครั้งแรกที่เราตรวจสอบว่ามีประเภทσ *ถ้าเป็นเช่นนั้นก็σจะเป็นมาตรฐาน (โมดูโลของกิราร์ด) และมันจะถูกทำให้เป็นมาตรฐาน (ดังนั้นจึงσกลายเป็นรูปแบบที่ดีโดย (0) SUBSยังทำให้นิพจน์ทั่วไปรักษา (0)

สิ่งนี้เรียกว่าการตรวจสอบประเภทสองทิศทาง ด้วยเหตุนี้เราจึงไม่จำเป็นต้องใส่คำอธิบายประกอบแลมบ์ดาทุกประเภท: หากเป็นที่รู้จักกันในf xประเภทของแลมบ์ดาจะถูกตรวจสอบกับประเภทของการโต้แย้งที่ได้รับแทนที่จะเป็นการอนุมานและเปรียบเทียบกับความเสมอภาค แต่ถ้าเป็นแลมบ์ดาคุณจะต้องมีคำอธิบายประกอบแบบชัดแจ้ง (มีคำอธิบายประกอบอยู่ในไวยากรณ์และทุก ๆ ที่คุณสามารถเพิ่มหรือสร้าง)fxffAnn Term Termλ' (σ : Term) (v : Var)

นอกจากนี้ให้ดูที่ง่ายขึ้นง่ายขึ้น! โพสต์บล็อก.


1
อันดับสอง "เรียบง่ายขึ้น"

กฎการลดครั้งแรกของ forall ดูแปลก ๆ ต่างจาก lambdas ไม่ควรใช้ foralls ด้วยวิธีที่ถูกต้อง (ใช่ไหม)

@chi ฉันไม่เข้าใจสิ่งที่คุณพูด บางทีอาจจะเป็นสัญกรณ์ของฉันคือเลว: กฎลดลงกล่าวว่า~>(λ v. b ∈ ∀ (v : σ). τ) (t ∈ σ) SUBS(b, v, t) ∈ SUBS(τ, v, t)
user3237465

1
ฉันพบสัญกรณ์ที่ทำให้เข้าใจผิด ดูเหมือนว่าถ้าคุณมีสองกฎหนึ่งสำหรับเรื่องไร้สาระอีกความหมาย(∀ (v : σ). τ) t ~> ... (λ v. b) t ~> ...ฉันจะลบรายการแรกและเปลี่ยนเป็นความคิดเห็นด้านล่าง

1
กฎ (1) มีข้อสรุปเป็นหลักฐาน คุณสามารถเปรียบเทียบความเรียบง่ายของระบบของคุณกับรุ่นสองทิศทางได้ก็ต่อเมื่อคุณมีระบบที่ใช้งานได้ คุณอาจพูดว่าคุณรักษาทุกอย่างให้เป็นมาตรฐาน แต่กฎของคุณไม่ได้

24

Let's have a go. I'll not bother about Girard's paradox, because it distracts from the central ideas. I will need to introduce some presentational machinery about judgments and derivations and such.

ไวยากรณ์

เงื่อนไข :: = (Elim) | * | (Var: Term) →คำศัพท์ | λVar↦Term

Elim :: = Term: Term | Var | กำจัดระยะ

The grammar has two mutually defined forms, "terms" which are the general notion of thing (types are things, values are things), including * (the type of types), dependent function types, and lambda-abstractions, but also embedding "eliminations" (i.e. "usages" rather than "constructions"), which are nested applications where the thing ultimately in the function position is either a variable or a term annotated with its type.

Reduction Rules

(λy↦t : (x:S)→T) s ↝ t[s:S / y] : T[s:S / x]

(t : T) ↝ t

The substitution operation t[e / x] replaces every occurrence of the variable x with the elimination e, avoiding name capture. To form an application that can reduce, a lambda term must be annotated by its type to make an elimination. The type annotation gives the lambda-abstraction a kind of "reactivity", allowing application to proceed. Once we reach the point where no more application is happening and the active t : T is being embedded back into the term syntax, we can drop the type annotation.

ลองขยายความสัมพันธ์ในการลด by โดยการปิดโครงสร้าง: กฎจะใช้ที่ใดก็ได้ภายในข้อกำหนดและการกำจัดที่คุณสามารถหาสิ่งที่ตรงกับด้านซ้ายมือ เขียน↝ * สำหรับการปิดการสะท้อนแสง (0 หรือมากกว่า) การปิด↝ ระบบการลดที่เกิดขึ้นนั้นไหลมารวมกันในแง่นี้:

ถ้า s ↝ * p และ s ↝ * q มี ​​r บางอย่างที่ p p * r และ q ↝ * r

บริบท

บริบท :: = | บริบท Var: Term

บริบทเป็นลำดับที่กำหนดประเภทให้กับตัวแปรเพิ่มขึ้นทางด้านขวาซึ่งเราคิดว่าเป็นจุดสิ้นสุด "ท้องถิ่น" บอกเราเกี่ยวกับตัวแปรที่ถูกผูกไว้ล่าสุด คุณสมบัติที่สำคัญของบริบทคือมันเป็นไปได้เสมอที่จะเลือกตัวแปรที่ไม่ได้ใช้ในบริบท เรารักษาค่าคงที่ว่าตัวแปรที่กำหนดประเภทในบริบทนั้นแตกต่างกัน

คำตัดสิน

การตัดสิน :: = บริบท⊢คำศัพท์มีเงื่อนไข | บริบท⊢ Elim เป็นคำศัพท์

นั่นคือไวยากรณ์ของการตัดสิน แต่จะอ่านอย่างไร สำหรับการเริ่มต้น⊢คือสัญลักษณ์ "turnstile" แบบดั้งเดิมที่แยกข้อสันนิษฐานออกจากข้อสรุป: คุณสามารถอ่านได้อย่างไม่เป็นทางการว่า "พูดว่า"

G ⊢ T มี t

หมายความว่าบริบทที่กำหนด G พิมพ์ T ยอมรับคำ t;

G ⊢ e คือ S

หมายความว่าบริบทที่กำหนด G, การกำจัด e จะได้รับประเภท S

คำตัดสินมีโครงสร้างที่น่าสนใจ: ศูนย์หรือมากกว่าปัจจัยการผลิตอย่างใดอย่างหนึ่งหรือมากกว่าเรื่อง , ศูนย์หรือมากกว่าเอาท์พุท

INPUTS                   SUBJECT        OUTPUTS
Context |- Term   has    Term
Context |-               Elim      is   Term

นั่นคือเราต้องเสนอประเภทของข้อตกลงล่วงหน้าและเพียงตรวจสอบพวกเขา แต่เราสังเคราะห์ประเภทของการกำจัด

กฎการพิมพ์

ฉันนำเสนอสิ่งเหล่านี้ในรูปแบบ Prolog ที่คลุมเครือเขียน J -: P1; ... ; Pn เพื่อระบุว่าการตัดสิน J เก็บไว้ถ้าสถานที่ P1 ถึง Pn ถือเช่นกัน หลักฐานจะเป็นคำพิพากษาอีกฉบับหนึ่ง

ข้อตกลงและเงื่อนไข

G ⊢ T มี t -: T ↝ R; G ⊢ R มี t

G ⊢ * มี *

G ⊢ * มี (x: S) → T -: G ⊢ * มี S; G, z: S! - * มี T [z / x]

G ⊢ (x: S) → T มีλy↦t -: G, z: S ⊢ T [z / x] มี t [z / y]

G ⊢ T มี (e) -: G ⊢ e คือ T

ตัดบัญชี

G ⊢ e คือ R -: G ⊢ e คือ S; S ↝ R

G, x: S, G '⊢ x คือ S

G ⊢ fs คือ T [s: S / x] -: G ⊢ f คือ (x: S) → T; G ⊢ S มี s

และนั่นมัน!

มีเพียงสองกฎเท่านั้นที่ไม่ได้กำกับด้วยไวยากรณ์: กฎที่บอกว่า "คุณสามารถลดประเภทก่อนที่คุณจะใช้เพื่อตรวจสอบคำศัพท์" และกฎที่ระบุว่า "คุณสามารถลดประเภทได้หลังจากคุณสังเคราะห์จากการกำจัด" หนึ่งในกลยุทธ์ที่ทำงานได้คือการลดประเภทจนกว่าคุณจะได้สัมผัสกับคอนสตรัคเตอร์สูงสุด

ระบบนี้ไม่ได้ทำให้เป็นมาตรฐานอย่างปกติ (เพราะ Girard's Paradox ซึ่งเป็นคนโกหก - สไตล์ขัดแย้งตนเองอ้างอิง) แต่มันสามารถทำให้ปกติ normalizing อย่างยิ่งโดยแยก * เป็น "ระดับจักรวาล" ซึ่งค่าที่เกี่ยวข้องกับประเภทต่าง ๆ ในระดับล่างระดับตัวเอง มีประเภทในระดับที่สูงขึ้นป้องกันการอ้างอิงตนเอง

อย่างไรก็ตามระบบนี้มีคุณสมบัติในการสงวนรักษาประเภทในแง่นี้

หาก G ⊢ T มี t และ G ↝ * D และ T ↝ * R และ t ↝ r ดังนั้น D ⊢ R มี r

ถ้า G ⊢ e คือ S และ G ↝ * D และ e ↝ f แสดงว่ามี R เช่นนั้นที่ S ↝ * R และ D ⊢ f เป็น R

บริบทสามารถคำนวณได้โดยอนุญาตให้ใช้คำที่มีในการคำนวณ นั่นคือถ้าการตัดสินนั้นถูกต้องในตอนนี้คุณสามารถคำนวณอินพุตได้มากเท่าที่คุณต้องการและหัวเรื่องในขั้นตอนเดียวและจากนั้นมันจะเป็นไปได้ที่จะคำนวณผลลัพธ์ของมันเพื่อให้แน่ใจว่าการตัดสินที่เกิดขึ้นนั้นยังคงใช้ได้ การพิสูจน์เป็นการเหนี่ยวนำง่าย ๆ ในการพิมพ์ที่ได้มาจากการบรรจบกันของ -> *

แน่นอนฉันได้แสดงเฉพาะแกนการทำงานที่นี่ แต่ส่วนขยายสามารถเป็นแบบแยกส่วนได้ นี่คือคู่

ภาคเรียน :: = ... | (x: S) * T | เซนต์

Elim :: = ... | e.head | e.tail

(s, t: (x: S) * T) .head ↝ s: S

(s, t: (x: S) * T). tail ↝ t: T [s: S / x]

G ⊢ * มี (x: S) * T -: G ⊢ * มี S; G, z: S ⊢ * มี T [z / x]

G ⊢ (x: S) * T มี s, t -: G ⊢ S มี s; G ⊢ T [s: S / x] มี t

G ⊢ e.head is S   -:   G ⊢ e is (x:S)*T

G ⊢ e.tail is T[e.head / x]   -:   G ⊢ e is (x:S)*T


1
G, x:S, G' ⊢ x is S -: G' ⊬ x?
user3237465

1
@user3237465 Nope. Thanks! Fixed. (When I was replacing ascii art turnstiles with html turnstiles (thus making them invisible on my phone; sorry if that's happening elsewhere) I missed that one.)

1
Oh, I thought you were just pointing out the typo. The rule says that, for each variable in the context, we synthesize the type that the context assigns it. When introducing contexts, I said "We maintain the invariant that the variables ascribed types in the context are distinct." so shadowing is disallowed. You'll see that every time the rules extend the context, they always choose of a fresh "z" which instantiates whatever binders we're stepping under. Shadowing is anathema. If you have context x : *, x : x then the type of the more local x is no longer ok because it's the x out of scope.

1
I just wanted you and the other answerers to know that I'm coming back to this thread every break from work. I really want to learn this, and for the first ime I fell like I actually get most of it. The next step will be implementing and writing a few programs. I'm delighted to be able to live in an era where information about such wonderful topics are available across the globe to someone like me, and that is all thanks to geniuses like you who dedicate some time of their life to spread that knowledge, for free, on the internet. Sorry again for phrasing my question badly, and thank you!
MaiaVictor

1
@cody Yes, there is no expansion. To see why it's not necessary, note that the two computation rules allow you to deploy the strategy where you normalize types completely before you check terms, and you also normalize types immediately after synthesizing them from eliminations. So in the rule where the types must match, they are already normalized, hence equal on the nose if the "original" checked and synthesized types were convertible. Meanwhile, restricting equality checks to that place only is ok because of this fact: if T is convertible to a canonical type, it reduces to a canonical type.
pigworker

8

The Curry-Howard correspondence says that there is a systematic correspondence between type systems and proof systems in logic. Taking a programmer-centric view of this, you could recast it this way:

  • Logical proof systems are programming languages.
  • These languages are statically typed.
  • The type system's responsibility in such a language is to forbid programs that would construct unsound proofs.

Seen from this angle:

  • The untyped lambda calculus that you summarize doesn't have a significant type system, so a proof system built on it would be unsound.
  • The simply typed lambda calculus is a programming language that has all the types necessary to build sound proofs in sentential logic ("if/then", "and", "or", "not"). But its types aren't good enough to check proofs that involve quantifiers ("for all x, ..."; "there exists an x such that ...").
  • Dependently typed lambda calculus has types and rules that support sentential logic and first-order quantifiers (quantification over values).

นี่คือกฎของธรรมชาติสำหรับการหักตรรกะลำดับแรกโดยใช้แผนภาพจากมีรายการวิกิพีเดียหักธรรมชาติ เหล่านี้เป็นกฎของแคลคูลัสแลมบ์ดาที่พิมพ์ได้น้อยที่สุดเช่นกัน

First-order natural deduction

โปรดทราบว่ากฎมีข้อกำหนดแลมบ์ดาในพวกเขา สิ่งเหล่านี้สามารถอ่านได้ในขณะที่โปรแกรมที่สร้างบทพิสูจน์ของประโยคที่แสดงตามประเภทของพวกเขา (หรือมากกว่านั้นอย่างชัดเจนเราแค่พูดว่าโปรแกรมเป็นบทพิสูจน์ ) กฎการลดที่คล้ายกันซึ่งคุณให้สามารถใช้ได้กับข้อกำหนดแลมบ์ดาเหล่านี้


ทำไมเราถึงสนใจเรื่องนี้ ก่อนอื่นเลยเพราะการพิสูจน์อาจกลายเป็นเครื่องมือที่มีประโยชน์ในการเขียนโปรแกรมและการมีภาษาที่สามารถทำงานกับการพิสูจน์ได้เมื่อวัตถุชั้นหนึ่งเปิดหลายช่องทาง ตัวอย่างเช่นหากฟังก์ชันของคุณมีเงื่อนไขก่อนที่จะเขียนลงในความคิดเห็นคุณสามารถเรียกร้องให้พิสูจน์ได้ว่าเป็นอาร์กิวเมนต์

ประการที่สองเพราะเครื่องจักรระบบประเภทที่จำเป็นในการจัดการปริมาณอาจมีการใช้งานอื่น ๆ ในบริบทการเขียนโปรแกรม โดยเฉพาะอย่างยิ่งภาษาที่พิมพ์ได้พึ่งพาจัดการปริมาณสากล ("สำหรับทุก x, ... ") โดยใช้แนวคิดที่เรียกว่าประเภทฟังก์ชั่นที่ขึ้นอยู่กับ - ฟังก์ชั่นที่ประเภทของผลคงที่สามารถขึ้นอยู่กับค่ารันไทม์ของการโต้แย้ง

เพื่อให้แอปพลิเคชันทางเดินเท้านี้ฉันเขียนโค้ดตลอดเวลาที่ต้องอ่านไฟล์Avroที่ประกอบด้วยระเบียนที่มีโครงสร้างเหมือนกัน - ทั้งหมดแบ่งปันชื่อและประเภทของชุดข้อมูลที่เหมือนกัน สิ่งนี้ทำให้ฉันต้อง:

  1. ฮาร์ดโค้ดโครงสร้างของเรกคอร์ดในโปรแกรมเป็นชนิดเรกคอร์ด
    • ข้อดี: รหัสนั้นง่ายกว่าและคอมไพเลอร์สามารถตรวจจับข้อผิดพลาดในรหัสของฉัน
    • Disadvantage: The program is hardcoded to read files that agree with the record type.
  2. Read the schema of the data at runtime, represent it generically as a data structure, and use that to process records generically
    • Advantages: My program is not hardcoded to just one file type
    • Disadvantages: The compiler can't catch as many errors.

อย่างที่คุณเห็นในหน้าการสอนของAvro Javaพวกเขาจะแสดงวิธีใช้ไลบรารีตามแนวทางทั้งสองนี้

ด้วยฟังก์ชั่นที่ขึ้นอยู่กับประเภทคุณสามารถมีเค้กและกินได้ด้วยค่าใช้จ่ายของระบบประเภทที่ซับซ้อนมากขึ้น คุณสามารถเขียนฟังก์ชั่นที่อ่านแฟ้มรว์, สารสกัดจากสคีและผลตอบแทนที่เนื้อหาของไฟล์เป็นกระแสของระเบียนที่มีประเภทขึ้นอยู่กับสคีมาเก็บไว้ในแฟ้มแบบคงที่ คอมไพเลอร์จะสามารถตรวจจับข้อผิดพลาดที่ตัวอย่างเช่นฉันพยายามเข้าถึงฟิลด์ที่มีชื่อซึ่งอาจไม่มีอยู่ในบันทึกของไฟล์ที่จะประมวลผลขณะรันไทม์ น่ารักเหรอ?


1
ประเภทอาคารที่รันไทม์ในแบบที่คุณพูดถึงเป็นสิ่งที่เจ๋งจริงๆที่ฉันไม่ได้คิด ค่อนข้างหวานแน่นอน! ขอบคุณสำหรับคำตอบที่ลึกซึ้ง
MaiaVictor
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.