ทำไม ghci desugar จึงพิมพ์รายการและพิมพ์ครอบครัว สามารถเลือกปิดใช้งานได้หรือไม่?


93

ฉันกำลังพยายามทำให้ประเภท ghci แสดงสำหรับไลบรารีของฉันให้ใช้งานง่ายที่สุด แต่ฉันพบปัญหามากมายเมื่อใช้คุณสมบัติประเภทขั้นสูงเพิ่มเติม

สมมติว่าฉันมีรหัสนี้ในไฟล์:

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}

import GHC.TypeLits

data Container (xs::[*]) = Container

ฉันโหลดเป็น ghci จากนั้นพิมพ์คำสั่งต่อไปนี้:

ghci> :t undefined :: Container '[String,String,String,String,String]

น่าเสียดายที่ ghci ทำให้ฉันดูค่อนข้างน่าเกลียด:

:: Container
       ((':)
          *
          String
          ((':)
             * String ((':) * String ((':) * String ((':) * String ('[] *))))))

ghci ได้ลบน้ำตาลสำหรับสตริงระดับประเภท มีวิธีใดบ้างที่จะป้องกันไม่ให้ ghci ทำสิ่งนี้และให้ฉันเป็นเวอร์ชั่นที่น่ารัก?


ในบันทึกที่เกี่ยวข้องสมมติว่าฉันสร้างReplicateฟังก์ชันระดับประเภท

data Nat1 = Zero | Succ Nat1

type family Replicate (n::Nat1) x :: [*]
type instance Replicate Zero x = '[]
type instance Replicate (Succ n) x = x ': (Replicate n x)

type LotsOfStrings = Replicate (Succ (Succ (Succ (Succ (Succ Zero))))) String

ตอนนี้เมื่อฉันถาม ghci สำหรับประเภทโดยใช้LotsOfStrings:

ghci> :t undefined :: Container LotsOfStrings

ghci ดีและให้ผลลัพธ์ที่สวยงาม:

undefined :: Container LotsOfStrings

แต่ถ้าฉันขอReplicateรุ่น d

ghci> :t undefined :: Container (Replicate (Succ (Succ (Succ (Succ (Succ Zero))))) String)

ghci แทนที่ในตระกูล type เมื่อไม่ได้ทำเช่นนั้นสำหรับคำพ้องประเภท:

:: Container
       ((':)
          *
          [Char]
          ((':)
             * [Char] ((':) * [Char] ((':) * [Char] ((':) * [Char] ('[] *))))))

เหตุใด ghci จึงทำการแทนที่ type family แต่ไม่ใช่ type synonym มีวิธีควบคุมเมื่อ ghci ทำการเปลี่ยนตัวหรือไม่?


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

วิธีแก้ปัญหาอยู่ในคำถามของคุณ - สร้างคำพ้องความหมายหากคุณต้องการย่อ
AndrewC

2
@AndrewC ฉันเพิ่งคิดคำถามอื่นที่เกี่ยวข้องกับความคิดเห็นของคุณ: ทำไมบางครั้งประเภทของสตริงจึงแสดงเป็น[Char]และบางครั้งก็แสดงเป็นString?
Mike Izbicki

1
ฉันคิดว่า ghci พยายามรักษาคำพ้องความหมายประเภทที่พบในแหล่งที่มา นั่นคือถ้าฟังก์ชั่นคือการประกาศที่จะเป็นชนิดนั้นชนิดของผลของมันจะแสดงเป็นString->String Stringอย่างไรก็ตามหากต้องสร้างประเภทจากชิ้นส่วนเช่น"abc"(ซึ่งเหมือนกับ'a':'b':'c':[]) ไม่มีคำพ้องที่จะรักษา นี่คือการเก็งกำไรล้วนๆ
. 'สรรพนาม' ม.

4
@nm: โปรดทราบว่า GHC พยายามที่จะรักษาชื่อของตัวแปรประเภทในลักษณะเดียวกันเมื่อประเภทที่อนุมานทั่วไปมากขึ้นรวมกับตัวแปรชนิดที่มีชื่อทั่วไปน้อยกว่าอย่างชัดเจน ฉันสงสัยว่าถ้าประเภท Explicit Stringถูกรวมเข้ากับตัวแปร type f aหรือ[a]จะแสดงใน[Char]ภายหลังด้วยเหตุผลที่คล้ายคลึงกัน
CA McCann

คำตอบ:


2

วิธีแก้ปัญหาที่ฉันรู้คือการใช้: kind ตัวอย่างเช่น

ghci>: kind (คอนเทนเนอร์ '[String, String, String, String, String])

ให้:

(คอนเทนเนอร์ '[String, String, String, String, String]) :: *

ในขณะที่

ghci>: ใจดี! (คอนเทนเนอร์ '[String, String, String, String, String])

จะพิมพ์สิ่งนี้:

คอนเทนเนอร์

((':)

  *
  [Char]
  ((':)
     * [Char] ((':) * [Char] ((':) * [Char] ((':) * [Char] ('[] *))))))

แน่นอนอย่างเป็นทางการคุณกำลังถามคำถามอื่นกับ ghci kindแต่มันได้ผล การใช้undefined ::เป็นวิธีแก้ปัญหาอย่างใดอย่างหนึ่งดังนั้นฉันคิดว่ามันอาจจะเพียงพอ


ฉันใช้undefined ::เพื่อยกตัวอย่างง่ายๆเท่านั้น ปัญหาที่แท้จริงคือเมื่อคุณได้รับข้อความแสดงข้อผิดพลาดที่มีรายการประเภทต่างๆเป็นพันรายการ การพิมพ์ออกมาต้องใช้เวลาหลายหน้าและแยกวิเคราะห์ได้ยากมาก
Mike Izbicki

ใช่ยุติธรรมพอ ได้ตระหนักว่า ฉันเป็นหนี้คุณคำตอบที่ดีกว่า
user2141650

2

สิ่งนี้ได้รับการแก้ไขใน GHC 7.8 ที่กำลังจะมาถึง

GHC 7.6 พิมพ์ชนิดถ้าประเภทข้อมูลใช้ PolyKinds ดังนั้นคุณจะเห็นแทนเพียง(':) * String ('[] *)(':) String '[]

ใน GHC 7.8 ชนิดจะไม่แสดงตามค่าเริ่มต้นอีกต่อไปและประเภทข้อมูลของคุณจะพิมพ์ออกมาเป็นรายการอย่างที่คุณคาดหวัง คุณสามารถใช้แฟล็กใหม่-fprint-explicit-kindsเพื่อดูประเภทที่ชัดเจนได้เช่นเดียวกับใน GHC 7.6 ฉันไม่ทราบสาเหตุของสิ่งนี้สันนิษฐานว่าประเภทที่ชัดเจนน่าจะเป็นตัวช่วยในการทำความเข้าใจ PolyKinds


0
import GHC.TypeLits

data Container (xs::[*]) = Container

ฉันโหลดเป็น ghci จากนั้นพิมพ์คำสั่งต่อไปนี้:

:t undefined :: Container '[String,String,String,String,String]

ดังนั้น...? คุณยังได้รับผลที่ได้กลับ desugared String ((':) * String ((':) * String ((':) * ...ฉันคิดว่านั่นคือ
leftaround ประมาณ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.