การอนุมานประเภทด้วยประเภทผลิตภัณฑ์


15

ฉันกำลังทำงานกับคอมไพเลอร์สำหรับภาษาที่ต่อกันและต้องการเพิ่มการสนับสนุนการอนุมานประเภท ฉันเข้าใจ Hindley - Milner แต่ฉันได้เรียนรู้ทฤษฎีประเภทเมื่อฉันไปดังนั้นฉันไม่แน่ใจว่าจะปรับตัวอย่างไร ระบบต่อไปนี้เป็นระบบเสียงที่ดี

คำคือตัวอักษรองค์ประกอบของคำพูดคำพูดของคำหรือดั้งเดิม

e::=x|ee|[e]|…

เงื่อนไขทั้งหมดแสดงถึงฟังก์ชั่น สำหรับสองฟังก์ชั่นและ ,นั่นคือ juxtaposition แสดงถึงการจัดองค์ประกอบย้อนกลับ ตัวอักษรหมายถึงฟังก์ชั่น niladice 2e1e2e1e2=e2∘e1

คำอื่น ๆ นอกเหนือจากการแต่งมีกฎประเภทพื้นฐาน:

x:ι[Lit]Γ⊢e:σΓ⊢[e]:∀α.α→σ×α[Quot],α not free in Γ

ไม่มีกฎระเบียบสำหรับการประยุกต์ใช้สะดุดตาเนื่องจากภาษาที่เรียงต่อกันขาด

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

τ::=ι|α|ρ→ρρ::=()|τ×ρσ::=τ|∀α.σ

นี่เป็นสิ่งแรกที่ดูเหมือนผู้ต้องสงสัย แต่ฉันไม่รู้แน่ชัดว่าเกิดอะไรขึ้นกับมัน

เพื่อช่วยให้สามารถอ่านและลดวงเล็บได้ฉันจะสมมติว่าในแบบแผนชุด ฉันจะใช้อักษรตัวใหญ่สำหรับตัวแปรที่แสดงถึงสแต็กแทนที่จะเป็นค่าเดียวab=b×(a)

มีหกดั้งเดิม ห้าคนแรกนั้นไม่น่ากลัวเลย dupใช้ค่าสูงสุดและสร้างสำเนาสองชุด swapเปลี่ยนลำดับของค่าสองอันดับแรก popทิ้งค่าบนสุด quoteรับค่าและสร้างใบเสนอราคา (ฟังก์ชัน) ที่ส่งคืน applyใช้ใบเสนอราคากับสแต็ก

dup::∀Ab.Ab→Abbswap::∀Abc.Abc→Acbpop::∀Ab.Ab→Aquote::∀Ab.Ab→A(∀C.C→Cb)apply::∀AB.A(A→B)→B

Combinator ที่ผ่านมาcomposeควรจะใช้เวลาสองใบเสนอราคาและผลตอบแทนประเภทของการเรียงต่อกันของพวกเขานั่นคือe_2] ในภาษาที่เรียงต่อกันแบบคงที่ประเภทของแมวนั้นตรงไปตรงมามาก[e1][e2]compose=[e1e2]compose

compose::∀ABCD.A(B→C)(C→D)→A(B→D)

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

compose::∀ABCDE.A(B→C)(D→E)→A…

หากคุณให้แสดงถึงความแตกต่างของสองประเภทฉันคิดว่าคุณสามารถเขียนประเภทได้อย่างถูกต้อง∖compose

compose::∀ABCDE.A(B→C)(D→E)→A((D∖C)B→((C∖D)E))

นี้ยังคงค่อนข้างตรงไปตรงมา: composeใช้ฟังก์ชั่นและE ผลกินมันยอดการบริโภคของไม่ได้ผลิตโดยและผลิตบนยอดการผลิตของไม่บริโภคโดยF_2สิ่งนี้ให้กฎสำหรับการแต่งเพลงธรรมดาf 2 : D → E B f 2 f 1 D f 1 f 2f1:B→Cf2:D→EBf2f1Df1f2

Γ⊢e1:∀AB.A→BΓ⊢e2:∀CD.C→DΓ⊢e1e2:((C∖B)A→((B∖C)D))[Comp]

อย่างไรก็ตามฉันไม่รู้ว่าสมมุติฐานนี้สอดคล้องกับอะไรจริง ๆ และฉันก็ไล่ตามมันไปเป็นวงกลมนานพอที่ฉันคิดว่าฉันเลี้ยวผิด มันเป็นความแตกต่างง่ายๆของ tuples ไหม?∖

∀A.()∖A=()∀A.A∖()=A∀ABCD.AB∖CD=B∖D iff A=Cotherwise=undefined

มีบางสิ่งที่แตกสลายอย่างมากเกี่ยวกับเรื่องนี้ที่ฉันไม่เห็นหรือว่าฉันชอบเส้นทางที่ถูกต้อง? (ฉันอาจบอกปริมาณของสิ่งนี้ผิดและชื่นชมการแก้ไขในพื้นที่นั้นด้วย)


คุณใช้ตัวแปรในไวยากรณ์อย่างไร คำถามนี้จะช่วยคุณในการจัดการ "subtyping" ที่คุณต้องการ
— jmad

1
@jmad: ฉันไม่แน่ใจว่าฉันเข้าใจคำถาม ตัวแปรประเภทเป็นเพียงเพื่อประโยชน์ในการกำหนดรูปแบบประเภทอย่างเป็นทางการและภาษาเองไม่มีตัวแปรเลยเพียงแค่คำจำกัดความซึ่งสามารถ [ซ้ำกัน] ซ้ำ
— Jon Purdy

ยุติธรรมพอสมควร คุณพูดได้ไหมว่าทำไม (อาจเป็นตัวอย่าง) กฎสำหรับcomposeเข้มงวดเกินไป? ฉันมีความประทับใจว่านี่เป็นแบบนี้ (เช่นข้อ จำกัดสามารถจัดการได้โดยการรวมเช่นสำหรับการใช้งานเช่นในC=D
— like-

@jmad: แน่นอน พิจารณาtwiceกำหนดเป็นdup compose applyซึ่งใช้คำพูดและใช้มันสองครั้ง [1 +] twiceเป็นเรื่องปกติ: คุณเขียนสองฟังก์ชั่นประเภท\แต่ไม่ใช่: ถ้า , ปัญหาคือดังนั้นการแสดงออกจึงไม่ได้รับอนุญาตแม้ว่ามันจะถูกต้องและมี พิมพ์A แน่นอนว่าวิธีแก้ปัญหาคือการวางผู้คัดเลือกไว้ในตำแหน่งที่ถูกต้อง แต่ส่วนใหญ่ฉันสงสัยว่าวิธีการเขียนประเภทของจริงโดยไม่มีคำจำกัดความวงกลม ∀ ขι→ι[pop] twiceA ≠ A∀Ab.f1,f2:Ab→A∀ A b .A≠Ab∀Ab.Abb→Acompose
— Jon Purdy

คำตอบ:


9

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

compose:∀ABCδ.δ (∀α.α A→αB) (∀β.β B→βC)→δ (∀γ.γ A→γC)

ตัวอักษรกรีกใช้สำหรับตัวแปร rest-of-the-stack เพื่อความชัดเจนเท่านั้น

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

การตรวจสอบประเภทประเภทอันดับ 2 นั้นไม่สามารถอธิบายได้โดยทั่วไปฉันเชื่อว่าแม้ว่าจะมีงานบางอย่างที่ได้ผลดีในทางปฏิบัติ (สำหรับ Haskell):

  • Simon L. Peyton Jones, Dimitrios Vytiniotis, Stephanie Weirich, Mark Shields: การอนุมานประเภทที่ใช้งานได้จริงสำหรับประเภทใดระดับหนึ่งโดยพลการ J. ฟังก์ชั่น โปรแกรม. 17 (1): 1-82 (2007)

กฎประเภทสำหรับการเรียบเรียงคือ:

Γ⊢e1:∀α.α A→α BΓ⊢e1:∀α.α B→α CΓ⊢e1 e2:∀α.α A→α C

ในการทำให้ระบบชนิดทำงานโดยทั่วไปคุณต้องมีกฎความเชี่ยวชาญต่อไปนี้:

Γ⊢e:∀α.α A→α BΓ⊢e:∀α.C A→α C B

ขอบคุณสิ่งนี้มีประโยชน์มาก ประเภทนี้ถูกต้องสำหรับฟังก์ชั่นของการโต้แย้งเดียว แต่มันไม่สนับสนุนการโต้แย้งหลาย ๆ ยกตัวอย่างเช่นdup +ควรจะมีประเภทเพราะมีประเภท\แต่การอนุมานประเภทหากไม่มีคำอธิบายประกอบเป็นข้อกำหนดที่แน่นอนดังนั้นฉันต้องกลับไปที่กระดานวาดภาพ ฉันมีความคิดสำหรับวิธีการอื่นในการติดตามแม้ว่าและจะบล็อกเกี่ยวกับมันถ้ามันได้ผล ιι→ι+ιι→ι
— Jon Purdy

1
ประเภทสแต็กเป็นจำนวนมากกว่าชิ้นส่วนสแต็กดังนั้นจึงไม่มีปัญหาในการจัดการกับสองฟังก์ชั่นการโต้แย้ง ฉันไม่แน่ใจว่าจะนำไปใช้กับวิธีนี้ได้อย่างไรdup +เนื่องจากไม่ได้ใช้การเขียนตามที่คุณกำหนดไว้ด้านบน
— Dave Clarke

Er [dup] [+] composeขวาฉันหมายถึง แต่ฉันอ่านเป็น ; พูด ; แล้วคุณมีและไม่alpha) การซ้อนไม่ถูกต้องเว้นแต่ว่าคุณจะพลิกกองซ้อนเพื่อให้ด้านบนเป็นองค์ประกอบสุดท้าย (ซ้อนกันที่สุด) B × α B = ι × ι ( ι × ι ) × α ι × ( ι × α )αBB×αB=ι×ι(ι×ι)×αι×(ι×α)
— Jon Purdy

ฉันอาจสร้างกองซ้อนของฉันในทิศทางที่ผิด ฉันไม่คิดว่าการทำรังมีความสำคัญตราบใดที่คู่ที่สร้างสแต็กไม่ปรากฏในภาษาการเขียนโปรแกรม (ฉันวางแผนที่จะอัปเดตคำตอบของฉัน แต่ต้องทำวิจัยเล็กน้อยก่อน)
— Dave Clarke

ใช่การทำรังเป็นรายละเอียดของการนำไปปฏิบัติค่อนข้างมาก
— Jon Purdy
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.