จะอ่าน "หลักฐาน" ของ GHC Core นี้ได้อย่างไร


84

ฉันเขียน Haskell เล็กน้อยเพื่อหาว่า GHC พิสูจน์ได้อย่างไรว่าสำหรับจำนวนธรรมชาติคุณสามารถลดจำนวนคู่ลงครึ่งหนึ่งเท่านั้น:

{-# LANGUAGE DataKinds, GADTs, KindSignatures, TypeFamilies #-}
module Nat where

data Nat = Z | S Nat

data Parity = Even | Odd

type family Flip (x :: Parity) :: Parity where
  Flip Even = Odd
  Flip Odd  = Even

data ParNat :: Parity -> * where
  PZ :: ParNat Even
  PS :: (x ~ Flip y, y ~ Flip x) => ParNat x -> ParNat (Flip x)

halve :: ParNat Even -> Nat
halve PZ     = Z
halve (PS a) = helper a
  where helper :: ParNat Odd -> Nat
        helper (PS b) = S (halve b)

ส่วนที่เกี่ยวข้องของแกนกลายเป็น:

Nat.$WPZ :: Nat.ParNat 'Nat.Even
Nat.$WPZ = Nat.PZ @ 'Nat.Even @~ <'Nat.Even>_N

Nat.$WPS
  :: forall (x_apH :: Nat.Parity) (y_apI :: Nat.Parity).
     (x_apH ~ Nat.Flip y_apI, y_apI ~ Nat.Flip x_apH) =>
     Nat.ParNat x_apH -> Nat.ParNat (Nat.Flip x_apH)
Nat.$WPS =
  \ (@ (x_apH :: Nat.Parity))
    (@ (y_apI :: Nat.Parity))
    (dt_aqR :: x_apH ~ Nat.Flip y_apI)
    (dt_aqS :: y_apI ~ Nat.Flip x_apH)
    (dt_aqT :: Nat.ParNat x_apH) ->
    case dt_aqR of _ { GHC.Types.Eq# dt_aqU ->
    case dt_aqS of _ { GHC.Types.Eq# dt_aqV ->
    Nat.PS
      @ (Nat.Flip x_apH)
      @ x_apH
      @ y_apI
      @~ <Nat.Flip x_apH>_N
      @~ dt_aqU
      @~ dt_aqV
      dt_aqT
    }
    }

Rec {
Nat.halve :: Nat.ParNat 'Nat.Even -> Nat.Nat
Nat.halve =
  \ (ds_dJB :: Nat.ParNat 'Nat.Even) ->
    case ds_dJB of _ {
      Nat.PZ dt_dKD -> Nat.Z;
      Nat.PS @ x_aIX @ y_aIY dt_dK6 dt1_dK7 dt2_dK8 a_apK ->
        case a_apK
             `cast` ((Nat.ParNat
                        (dt1_dK7
                         ; (Nat.Flip (dt2_dK8 ; Sym dt_dK6))_N
                         ; Nat.TFCo:R:Flip[0]))_R
                     :: Nat.ParNat x_aIX ~# Nat.ParNat 'Nat.Odd)
        of _
        { Nat.PS @ x1_aJ4 @ y1_aJ5 dt3_dKa dt4_dKb dt5_dKc b_apM ->
        Nat.S
          (Nat.halve
             (b_apM
              `cast` ((Nat.ParNat
                         (dt4_dKb
                          ; (Nat.Flip
                               (dt5_dKc
                                ; Sym dt3_dKa
                                ; Sym Nat.TFCo:R:Flip[0]
                                ; (Nat.Flip (dt_dK6 ; Sym dt2_dK8))_N
                                ; Sym dt1_dK7))_N
                          ; Sym dt_dK6))_R
                      :: Nat.ParNat x1_aJ4 ~# Nat.ParNat 'Nat.Even)))
        }
    }
end Rec }

ฉันรู้ขั้นตอนทั่วไปของการแคสต์ประเภทต่างๆผ่านอินสแตนซ์ของตระกูล Flip แต่มีบางสิ่งที่ฉันไม่สามารถทำตามได้ทั้งหมด:

  • ความหมายของ@~ <Nat.Flip x_apH>_Nอะไร? มันคืออินสแตนซ์ Flip สำหรับ x หรือไม่ แตกต่างจาก@ (Nat.Flip x_apH)อย่างไร? ฉันทั้งสนใจ< >และ_N

เกี่ยวกับการแสดงครั้งแรกในhalve:

  • สิ่งใดdt_dK6, dt1_dK7และdt2_dK8ยืน? ฉันเข้าใจว่ามันเป็นการพิสูจน์ความเท่าเทียม แต่แบบไหนล่ะ?
  • ฉันเข้าใจว่าSymวิ่งผ่านการเทียบเท่าย้อนกลับ
  • พวก;เขาทำอะไร? มีการใช้การพิสูจน์ความเท่าเทียมกันตามลำดับหรือไม่?
  • สิ่งเหล่านี้_Nและ_Rคำต่อท้ายคืออะไร?
  • เป็นTFCo:R:Flip[0]และTFCo:R:Flip[1]อินสแตนซ์ของ Flip หรือไม่?

6
ฉันไม่รู้ แต่เดาว่า _N และ _R เป็นบทบาทที่ระบุและเป็นตัวแทน: haskell.org/ghc/docs/latest/html/users_guide/…
ไค

เยี่ยมชมstackoverflow.com/questions/6121146/reading-ghc-core หวังว่าคุณจะได้รับความคิด ..
Hemant Ramphul

คำตอบ:


6

@~ คือแอปพลิเคชั่นบีบบังคับ

วงเล็บเหลี่ยมแสดงถึงการบีบบังคับแบบสะท้อนกลับของประเภทที่มีอยู่ด้วยบทบาทที่กำหนดโดยตัวอักษรขีดล่าง

ดังนั้นจึง<Nat.Flip x_ap0H>_Nเป็นข้อพิสูจน์ความเท่าเทียมที่Nat.Flip x_apHเท่ากับNat.Flip x_apHในนาม (เนื่องจากประเภทที่เท่ากันไม่ใช่แค่การแทนค่าเท่ากัน)

ปล. มีข้อโต้แย้งมากมาย เราดูตัวสร้างอัจฉริยะ$WPSและเราจะเห็นสองตัวแรกคือประเภทของ x และ y ตามลำดับ เรามีหลักฐานว่าอาร์กิวเมนต์ตัวสร้างคือFlip x(ในกรณีนี้เรามีFlip x ~ Evenจากนั้นเรามีการพิสูจน์x ~ Flip yและy ~ Flip xอาร์กิวเมนต์สุดท้ายคือค่าของParNat x.

ตอนนี้ฉันจะเดินผ่านนักแสดงประเภทแรก Nat.ParNat x_aIX ~# Nat.ParNat 'Nat.Odd

(Nat.ParNat ...)_Rเราเริ่มต้นด้วย นี่คือแอปพลิเคชันตัวสร้างประเภท มันยกหลักฐานx_aIX ~# 'Nat.OddการNat.ParNat x_aIX ~# Nat.ParNat 'Nat.Oddเป็น ความRหมายนี้แสดงความหมายโดยนัยว่าประเภทต่างๆเป็นไอโซมอร์ฟิก แต่ไม่เหมือนกัน (ในกรณีนี้เหมือนกัน แต่เราไม่ต้องการความรู้นั้นในการแสดง)

(dt1_dK7 ; (Nat.Flip (dt2_dK8 ; Sym dt_dK6))_N; Nat.TFCo:R:Flip[0])ตอนนี้เรามองไปที่ตัวหลักของหลักฐาน ;หมายถึงการขนส่งเช่นใช้การพิสูจน์เหล่านี้ตามลำดับ

dt1_dK7เป็นหลักฐานของx_aIX ~# Nat.Flip y_aIY.

ถ้าเรามองไปที่(dt2_dK8 ; Sym dt_dK6). แสดงให้เห็นว่าdt2_dK8 เป็นประเภท ดังนั้นเป็นชนิดและเป็นประเภทy_aIY ~# Nat.Flip x_aIXdt_dK6'Nat.Even ~# Nat.Flip x_aIXSym dt_dK6Nat.Flip x_aIX ~# 'Nat.Even(dt2_dK8 ; Sym dt_dK6)y_aIY ~# 'Nat.Even

ดังนั้นจึงเป็นข้อพิสูจน์ว่า(Nat.Flip (dt2_dK8 ; Sym dt_dK6))_NNat.Flip y_aIY ~# Nat.Flip 'Nat.Even

Nat.TFCo:R:Flip[0]Nat.Flip 'Nat.Even ~# 'Nat.Odd'เป็นกฎข้อแรกของพลิกซึ่งเป็น

เราได้(dt1_dK7 ; (Nat.Flip (dt2_dK8 ; Sym dt_dK6))_N; Nat.TFCo:R:Flip[0])ประเภทx_aIX #~ 'Nat.Oddมารวมกัน

การร่ายที่ซับซ้อนขึ้นเป็นครั้งที่สองนั้นยากกว่าเล็กน้อยในการทำงาน แต่ควรทำงานบนหลักการเดียวกัน


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