เทคนิคการติดตามข้อ จำกัด


322

นี่คือสถานการณ์: ผมเคยเขียนโค้ดบางประเภทที่มีลายเซ็นและ GHC บ่นไม่สามารถอนุมาน x ~ Y สำหรับบางคนและx yโดยทั่วไปคุณสามารถขว้าง GHC กระดูกและเพิ่ม isomorphism ให้กับข้อ จำกัด ของฟังก์ชันได้ แต่นี่เป็นความคิดที่ไม่ดีด้วยเหตุผลหลายประการ:

  1. ไม่เน้นการเข้าใจรหัส
  2. คุณสามารถจบลงด้วยข้อ จำกัด 5 ข้อที่ใครจะพอเพียง (ตัวอย่างเช่นหากข้อ 5 ถูกระบุโดยข้อ จำกัด เฉพาะอีกข้อหนึ่ง)
  3. คุณสามารถจบลงด้วยข้อ จำกัด ปลอมหากคุณทำอะไรผิดพลาดหรือหาก GHC ไม่ช่วยเหลือ

ฉันใช้เวลาหลายชั่วโมงในการต่อสู้คดี 3. ฉันเล่นด้วยsyntactic-2.0และผมพยายามที่จะกำหนดรุ่นโดเมนที่เป็นอิสระของคล้ายกับรุ่นที่กำหนดไว้ในshareNanoFeldspar.hs

ฉันมีสิ่งนี้:

{-# LANGUAGE GADTs, FlexibleContexts, TypeOperators #-}
import Data.Syntactic

-- Based on NanoFeldspar.hs
data Let a where
    Let :: Let (a :-> (a -> b) :-> Full b)

share :: (Let :<: sup,
          Domain a ~ sup,
          Domain b ~ sup,
          SyntacticN (a -> (a -> b) -> b) fi) 
      => a -> (a -> b) -> a
share = sugarSym Let

และ GHC could not deduce (Internal a) ~ (Internal b)ซึ่งไม่ใช่สิ่งที่ฉันต้องการ ดังนั้นฉันจึงได้เขียนรหัสบางอย่างที่ฉันไม่ได้ตั้งใจ (ซึ่งจำเป็นต้องมีข้อ จำกัด ) หรือ GHC ต้องการข้อ จำกัด นั้นเนื่องจากข้อ จำกัด อื่น ๆ ที่ฉันได้เขียนไว้

ปรากฎว่าฉันต้องการเพิ่ม(Syntactic a, Syntactic b, Syntactic (a->b))ในรายการข้อ จำกัด ซึ่งไม่มีนัย(Internal a) ~ (Internal b)ใด ฉันสะดุดกับข้อ จำกัด ที่ถูกต้อง ฉันยังไม่มีวิธีค้นหาอย่างเป็นระบบ

คำถามของฉันคือ:

  1. ทำไม GHC จึงเสนอข้อ จำกัด ดังกล่าว ไม่มีข้อ จำกัด ทางด้าน syntax Internal a ~ Internal bดังนั้น GHC จึงดึงสิ่งนั้นมาจากไหน
  2. โดยทั่วไปแล้วเทคนิคใดที่สามารถใช้ในการติดตามต้นกำเนิดของข้อ จำกัด ที่ GHC เชื่อว่าจำเป็น แม้สำหรับข้อ จำกัด ที่ฉันสามารถค้นพบตัวเองวิธีการของฉันเป็นหลักบังคับให้เส้นทางที่กระทำผิดโดยการเขียนข้อ จำกัด แบบเรียกซ้ำ วิธีการนี้โดยทั่วไปจะลงไปในโพรงกระต่ายที่ไม่มีที่สิ้นสุดและเป็นวิธีที่มีประสิทธิภาพน้อยที่สุดที่ฉันสามารถจินตนาการได้

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

12
@jozefg คุณมีลิงค์สำหรับการสนทนาหรือไม่?
crockeea

36
บ่อยครั้งที่มันช่วยในการลบลายเซ็นประเภทออกจนหมดและให้ ghci บอกคุณว่ามันควรจะเป็นลายเซ็นต์แบบไหน
Tobias Brandt

12
อย่างใดaและbจะผูกพัน - ดูที่ประเภทลายเซ็นนอกบริบทของคุณ - ไม่a -> (a -> b) -> a a -> (a -> b) -> bอาจจะใช่มั้ย ด้วยตัวแก้ไขข้อ จำกัด พวกเขาสามารถมีอิทธิพลต่อความเสมอภาคของสกรรมกริยาได้ทุกที่แต่ข้อผิดพลาดมักจะแสดงตำแหน่ง "ใกล้" กับตำแหน่งที่เกิดข้อ จำกัด นั่นจะเจ๋งมากแม้ว่า @jozefg - อาจมีข้อ จำกัด ในการใส่แท็กหรืออะไรสักอย่างเพื่อแสดงว่ามาจากไหน? : s
Athan Clark

คำตอบ:


6

ก่อนอื่นฟังก์ชันของคุณมีชนิดผิด ผมค่อนข้างมั่นใจว่ามันควรจะเป็น a -> (a -> b) -> b(ไม่มีบริบท) GHC 7.10 ค่อนข้างประโยชน์มากในการชี้ให้เห็นว่าเพราะมีรหัสต้นฉบับของคุณก็บ่นเกี่ยวกับข้อ Internal (a -> b) ~ (Internal a -> Internal a)จำกัด หลังจากแก้ไขshareประเภทของ GHC 7.10 แล้วยังคงมีประโยชน์ในการชี้นำเรา:

  1. Could not deduce (Internal (a -> b) ~ (Internal a -> Internal b))

  2. หลังจากเพิ่มข้างต้นเราจะได้รับ Could not deduce (sup ~ Domain (a -> b))

  3. หลังจากเพิ่มที่เราได้รับCould not deduce (Syntactic a), Could not deduce (Syntactic b)และCould not deduce (Syntactic (a -> b))

  4. หลังจากเพิ่มสามตัวนี้ลงไปมันก็พิมพ์เครื่องหมายลงในที่สุด ดังนั้นเราจึงจบลงด้วย

    share :: (Let :<: sup,
              Domain a ~ sup,
              Domain b ~ sup,
              Domain (a -> b) ~ sup,
              Internal (a -> b) ~ (Internal a -> Internal b),
              Syntactic a, Syntactic b, Syntactic (a -> b),
              SyntacticN (a -> (a -> b) -> b) fi)
          => a -> (a -> b) -> b
    share = sugarSym Let

ดังนั้นฉันจะบอกว่า GHC ไม่ได้ไร้ประโยชน์ในการนำเรา

สำหรับคำถามของคุณเกี่ยวกับการติดตามตำแหน่งที่ GHC ได้รับข้อกำหนดด้านข้อ จำกัด คุณสามารถลองใช้สถานะการดีบักของ GHCโดยเฉพาะ-ddump-tc-traceแล้วอ่านบันทึกผลลัพธ์เพื่อดูว่ามีการเพิ่มที่ไหนInternal (a -> b) ~ tและ(Internal a -> Internal a) ~ tเพิ่มเข้าไปในWantedชุด แต่จะอ่านนานมาก .


0

คุณลองสิ่งนี้ใน GHC 8.8+ หรือไม่

share :: (Let :<: sup,
          Domain a ~ sup,
          Domain b ~ sup,
          SyntacticN (a -> (a -> b) -> b) fi,
          _) 
      => a -> (a -> b) -> a
share = sugarSym Let

กุญแจสำคัญคือการใช้รูประเภทท่ามกลางข้อ จำกัด : _ => your difficult type

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