Độ phân giải loại lỗ không bình thường


105

Gần đây tôi đã phát hiện ra rằng các lỗ kiểu kết hợp với khớp mẫu trên các bản thử nghiệm mang lại trải nghiệm giống Agda khá tốt trong Haskell. Ví dụ:

{-# LANGUAGE
    DataKinds, PolyKinds, TypeFamilies, 
    UndecidableInstances, GADTs, TypeOperators #-}

data (==) :: k -> k -> * where
    Refl :: x == x

sym :: a == b -> b == a
sym Refl = Refl 

data Nat = Zero | Succ Nat

data SNat :: Nat -> * where
    SZero :: SNat Zero
    SSucc :: SNat n -> SNat (Succ n)

type family a + b where
    Zero   + b = b
    Succ a + b = Succ (a + b)

addAssoc :: SNat a -> SNat b -> SNat c -> (a + (b + c)) == ((a + b) + c)
addAssoc SZero b c = Refl
addAssoc (SSucc a) b c = case addAssoc a b c of Refl -> Refl

addComm :: SNat a -> SNat b -> (a + b) == (b + a)
addComm SZero SZero = Refl
addComm (SSucc a) SZero = case addComm a SZero of Refl -> Refl
addComm SZero (SSucc b) = case addComm SZero b of Refl -> Refl
addComm sa@(SSucc a) sb@(SSucc b) =
    case addComm a sb of
        Refl -> case addComm b sa of
            Refl -> case addComm a b of
                Refl -> Refl 

Điều thực sự tuyệt vời là tôi có thể thay thế các mặt bên phải của các Refl -> expcấu kiện bằng một lỗ loại và các loại mục tiêu lỗ của tôi được cập nhật với bằng chứng, khá giống với rewritebiểu mẫu trong Agda.

Tuy nhiên, đôi khi lỗ hổng cập nhật:

(+.) :: SNat a -> SNat b -> SNat (a + b)
SZero   +. b = b
SSucc a +. b = SSucc (a +. b)
infixl 5 +.

type family a * b where
    Zero   * b = Zero
    Succ a * b = b + (a * b)

(*.) :: SNat a -> SNat b -> SNat (a * b)
SZero   *. b = SZero
SSucc a *. b = b +. (a *. b)
infixl 6 *.

mulDistL :: SNat a -> SNat b -> SNat c -> (a * (b + c)) == ((a * b) + (a * c))
mulDistL SZero b c = Refl
mulDistL (SSucc a) b c = 
    case sym $ addAssoc b (a *. b) (c +. a *. c) of
        -- At this point the target type is
        -- ((b + c) + (n * (b + c))) == (b + ((n * b) + (c + (n * c))))
        -- The next step would be to update the RHS of the equivalence:
        Refl -> case addAssoc (a *. b) c (a *. c) of
            Refl -> _ -- but the type of this hole remains unchanged...

Ngoài ra, mặc dù các loại đích không nhất thiết phải xếp hàng bên trong bằng chứng, nhưng nếu tôi dán toàn bộ từ Agda vào thì nó vẫn kiểm tra tốt:

mulDistL' :: SNat a -> SNat b -> SNat c -> (a * (b + c)) == ((a * b) + (a * c))
mulDistL' SZero b c = Refl
mulDistL' (SSucc a) b c = case
    (sym $ addAssoc b (a *. b) (c +. a *. c),
    addAssoc (a *. b) c (a *. c),
    addComm (a *. b) c,
    sym $ addAssoc c (a *. b) (a *. c),
    addAssoc b c (a *. b +. a *. c),
    mulDistL' a b c
    ) of (Refl, Refl, Refl, Refl, Refl, Refl) -> Refl

Bạn có bất kỳ ý tưởng nào tại sao điều này xảy ra (hoặc làm thế nào tôi có thể viết lại bằng chứng một cách mạnh mẽ)?


8
Bạn không mong đợi một chút? So khớp mẫu trên một bằng chứng bình đẳng đang thiết lập một bình đẳng (hai chiều). Nó không rõ ràng ở đâu và theo hướng nào bạn muốn nó được áp dụng cho loại mục tiêu. Ví dụ: bạn có thể bỏ qua các symcuộc gọi mulDistL'và mã của bạn sẽ vẫn được kiểm tra.
kosmikus

1
Rất có thể tôi đang mong đợi quá nhiều. Tuy nhiên, trong nhiều trường hợp, nó hoạt động giống như trong Agda vì vậy sẽ vẫn hữu ích để tìm ra các quy luật của hành vi. Tuy nhiên, tôi không lạc quan, vì vấn đề có thể liên quan sâu sắc đến ruột của máy kiểm tra loại.
András Kovács

1
Nó hơi trực giao với câu hỏi của bạn, nhưng bạn có thể rút ra những cách chứng minh này bằng cách sử dụng một tập hợp các tổ hợp lập luận theo phương pháp cân bằng à la Agda. Cf bằng chứng này của khái niệm
gallais

Câu trả lời:


1

Nếu bạn muốn tạo tất cả các giá trị có thể có như vậy, thì bạn có thể viết một hàm để làm như vậy, với các giới hạn được cung cấp hoặc chỉ định.

Rất có thể sử dụng Chữ số Nhà thờ cấp loại hoặc một số như vậy để thực thi việc tạo ra những thứ này, nhưng chắc chắn là quá nhiều việc so với những gì bạn có thể muốn / cần.

Đây có thể không phải là điều bạn muốn (nghĩa là "Ngoại trừ việc chỉ sử dụng (x, y) vì z = 5 - x - y") nhưng nó có ý nghĩa hơn việc cố gắng có một số loại hạn chế bắt buộc đối với cấp loại để cho phép các giá trị.


-3

Nó xảy ra bởi vì các giá trị được xác định tại thời gian chạy. Nó có thể mang lại sự biến đổi các giá trị tùy thuộc vào những gì được nhập vào lúc chạy, do đó nó giả định rằng lỗ đã được cập nhật.


3
Tất nhiên các giá trị được xác định trong thời gian chạy, nhưng nó không liên quan gì đến câu hỏi. Thông tin cần thiết đã có sẵn từ đối sánh mẫu trên GADT.
int_index
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.