Bu GHC Çekirdeği “kanıtı” nasıl okunur?


84

Bu küçük Haskell parçasını, GHC'nin doğal sayılar için yalnızca çiftleri yarıya indirebileceğinizi nasıl kanıtladığını anlamak için yazdım:

{-# 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)

Çekirdeğin ilgili kısımları şu hale gelir:

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 }

Türleri Flip türü ailesinin örnekleriyle yayınlamanın genel akışını biliyorum, ancak tam olarak izleyemediğim bazı şeyler var:

  • Anlamı ne @~ <Nat.Flip x_apH>_N? x için Flip örneği mi? Bu nasıl farklıdır @ (Nat.Flip x_apH)? Her iki ilgilenen kulüpler < >ve_N

İlk oyuncu kadrosuyla ilgili olarak halve:

  • Ne yapmak dt_dK6, dt1_dK7ve dt2_dK8ayakta? Bir çeşit denklik kanıtı olduklarını anlıyorum, ama hangisi hangisi?
  • SymGeriye doğru bir denklikten geçtiğini anlıyorum
  • Ne işe ;yarar? Eşdeğerlik ispatları sırayla mı uygulanıyor?
  • Bunlar _Nve _Rson ekler nelerdir?
  • Are TFCo:R:Flip[0]ve TFCo:R:Flip[1]Flip örnekleri?

6
Hiçbir fikrim yok, ama benim tahminim, _N ve _R'nin nominal ve temsili roller olduğu: haskell.org/ghc/docs/latest/html/users_guide/…
chi,

Yanıtlar:


6

@~ zorlama uygulamasıdır.

Köşeli parantezler, altı çizili harf tarafından verilen rolle içerdikleri türden bir dönüşlü zorlamayı gösterir.

Böylece <Nat.Flip x_ap0H>_Nbir eşitlik kanıtıdır Nat.Flip x_apHeşittir Nat.Flip x_apH(eşit türleri değil, sadece eşit gösterimler gibi) ismen.

PS'nin birçok argümanı var. Akıllı kurucuya bakarız $WPSve ilk ikisinin sırasıyla x ve y türleri olduğunu görebiliriz. Yapıcı argümanının olduğuna dair kanıtımız var Flip x(bu durumda bizde var Flip x ~ Even. O zaman kanıtlarımız var x ~ Flip yve y ~ Flip x. Son argüman bir değerdir ParNat x.

Şimdi yazının ilk kadrosuna geçeceğim Nat.ParNat x_aIX ~# Nat.ParNat 'Nat.Odd

İle başlıyoruz (Nat.ParNat ...)_R. Bu bir tür oluşturucu uygulamasıdır. Bu kanıtı asansörler x_aIX ~# 'Nat.Oddiçin Nat.ParNat x_aIX ~# Nat.ParNat 'Nat.Odd. Bunu Rtemsili olarak yaptığı anlamına gelir, bu türlerin izomorfik olduğu ancak aynı olmadığı anlamına gelir (bu durumda bunlar aynıdır, ancak döküm yapmak için bu bilgiye ihtiyacımız yoktur).

Şimdi ispatın ana gövdesine bakıyoruz (dt1_dK7 ; (Nat.Flip (dt2_dK8 ; Sym dt_dK6))_N; Nat.TFCo:R:Flip[0]). ;transit anlamına gelir, yani bu ispatları sırayla uygulayın.

dt1_dK7bir kanıtıdır x_aIX ~# Nat.Flip y_aIY.

Bakarsak (dt2_dK8 ; Sym dt_dK6). dt2_dK8gösterir y_aIY ~# Nat.Flip x_aIX. dt_dK6tipidir 'Nat.Even ~# Nat.Flip x_aIX. Yani Sym dt_dK6tipte Nat.Flip x_aIX ~# 'Nat.Evenve (dt2_dK8 ; Sym dt_dK6)tiptey_aIY ~# 'Nat.Even

Böylelikle (Nat.Flip (dt2_dK8 ; Sym dt_dK6))_Nbunun bir kanıtıdır Nat.Flip y_aIY ~# Nat.Flip 'Nat.Even.

Nat.TFCo:R:Flip[0]çevirmenin ilk kuralı olan Nat.Flip 'Nat.Even ~# 'Nat.Odd'.

Bunları bir araya getirdiğimizde bir (dt1_dK7 ; (Nat.Flip (dt2_dK8 ; Sym dt_dK6))_N; Nat.TFCo:R:Flip[0])tür elde ederiz x_aIX #~ 'Nat.Odd.

İkinci daha karmaşık oyuncu kadrosunun çalışması biraz daha zordur, ancak aynı prensip üzerinde çalışması gerekir.


Gerçekten, birilerinin bu karmaşayı anlayıp anlamayacağını görmek için o gönderiyi ödüllendirdim ^^ aferin efendim.
Jiri Trecak
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.