Làm thế nào để đọc “bằng chứng” GHC Core này?


84

Tôi đã viết một đoạn nhỏ này của Haskell để tìm ra cách GHC chứng minh rằng đối với các số tự nhiên, bạn chỉ có thể giảm một nửa số chẵn:

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

Các phần có liên quan của cốt lõi trở thành:

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ôi biết quy trình chung của việc truyền các loại thông qua các trường hợp của họ Loại lật, nhưng có một số điều mà tôi hoàn toàn không thể làm theo:

  • Ý nghĩa của nó là @~ <Nat.Flip x_apH>_Ngì? nó có phải là phiên bản Flip cho x không? Làm thế nào để điều đó khác với @ (Nat.Flip x_apH)? Tôi vừa quan tâm đến < >_N

Về dàn diễn viên đầu tiên trong halve:

  • Làm gì dt_dK6, dt1_dK7và đại diện dt2_dK8cho điều gì? Tôi hiểu chúng là một số loại bằng chứng tương đương, nhưng đó là bằng chứng nào?
  • Tôi hiểu rằng Symđiều đó chạy ngược lại
  • Những gì làm được ;? Các chứng minh tương đương có được áp dụng tuần tự không?
  • Đây là gì _N_Rhậu tố là gì?
  • TFCo:R:Flip[0]TFCo:R:Flip[1]các trường hợp của Flip?

6
Tôi không biết, nhưng tôi đoán rằng _N và _R là vai trò đại diện và danh nghĩa: haskell.org/ghc/docs/latest/html/users_guide/…
chi

Thăm stackoverflow.com/questions/6121146/reading-ghc-core hy vọng bạn sẽ có được một ý tưởng ..
Hemant Ramphul

Câu trả lời:


6

@~ là ứng dụng cưỡng chế.

Các dấu ngoặc nhọn biểu thị một sự ép buộc phản xạ thuộc loại chứa của chúng với vai trò được cung cấp bởi chữ cái gạch dưới.

Như vậy <Nat.Flip x_ap0H>_Nlà một bằng chứng bình đẳng Nat.Flip x_apHlà bình đẳng Nat.Flip x_apHtrên danh nghĩa (như các loại bình đẳng không chỉ là các biểu diễn bình đẳng).

PS có rất nhiều đối số. Chúng ta nhìn vào hàm tạo thông minh $WPSvà chúng ta có thể thấy hai hàm đầu tiên là loại x và y tương ứng. Chúng tôi có bằng chứng rằng đối số của hàm tạo là Flip x(trong trường hợp này là chúng tôi có Flip x ~ Even. Sau đó chúng tôi có các bằng chứng x ~ Flip yy ~ Flip x. Đối số cuối cùng là một giá trị của ParNat x.

Bây giờ tôi sẽ đi qua dàn cast đầu tiên của loại Nat.ParNat x_aIX ~# Nat.ParNat 'Nat.Odd

Chúng tôi bắt đầu với (Nat.ParNat ...)_R. Đây là một ứng dụng phương thức khởi tạo kiểu. Nó nâng bằng chứng x_aIX ~# 'Nat.Oddđể Nat.ParNat x_aIX ~# Nat.ParNat 'Nat.Odd. Điều này Rcó nghĩa là nó thực hiện điều này về mặt biểu diễn nghĩa là các kiểu là đẳng cấu nhưng không giống nhau (trong trường hợp này chúng giống nhau nhưng chúng ta không cần kiến ​​thức đó để thực hiện ép kiểu).

Bây giờ chúng ta nhìn vào phần chính của bằng chứng (dt1_dK7 ; (Nat.Flip (dt2_dK8 ; Sym dt_dK6))_N; Nat.TFCo:R:Flip[0]). ;nghĩa là chuyển đổi tức là áp dụng các bằng chứng này theo thứ tự.

dt1_dK7là một bằng chứng của x_aIX ~# Nat.Flip y_aIY.

Nếu chúng ta nhìn vào (dt2_dK8 ; Sym dt_dK6). dt2_dK8cho thấy y_aIY ~# Nat.Flip x_aIX. dt_dK6là loại 'Nat.Even ~# Nat.Flip x_aIX. Vì vậy Sym dt_dK6là loại Nat.Flip x_aIX ~# 'Nat.Even(dt2_dK8 ; Sym dt_dK6)thuộc loạiy_aIY ~# 'Nat.Even

Như vậy (Nat.Flip (dt2_dK8 ; Sym dt_dK6))_Nlà một bằng chứng rằng Nat.Flip y_aIY ~# Nat.Flip 'Nat.Even.

Nat.TFCo:R:Flip[0]là quy tắc lật đầu tiên Nat.Flip 'Nat.Even ~# 'Nat.Odd'.

Kết hợp những thứ này lại với nhau, chúng ta sẽ có được (dt1_dK7 ; (Nat.Flip (dt2_dK8 ; Sym dt_dK6))_N; Nat.TFCo:R:Flip[0])loại x_aIX #~ 'Nat.Odd.

Dàn diễn viên thứ hai phức tạp hơn một chút khó thực hiện hơn nhưng sẽ hoạt động theo cùng một nguyên tắc.


Thực sự tôi chỉ truy cập bài viết đó để xem liệu ai đó có thể hiểu được mớ hỗn độn đó không ^^ làm tốt lắm thưa ông.
Jiri Trecak
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.