Düzensiz delik tipi çözünürlük


105

Son zamanlarda, provalarda desen eşleştirmeyle birleştirilen tip deliklerinin Haskell'de oldukça güzel bir Agda benzeri deneyim sağladığını öğrendim. Örneğin:

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

Gerçekten güzel olan şey, Refl -> expyapıların sağ taraflarını bir tip deliği ile değiştirebilmem ve delik hedef rewritetiplerimin hemen hemen Agda'daki formda olduğu gibi kanıtla güncellenmesi.

Ancak bazen delik güncellenemiyor:

(+.) :: 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...

Ayrıca, hedef türleri kanıtın içinde mutlaka sıralanmasa da, Agda'dan her şeyi yapıştırırsam yine de iyi kontrol eder:

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

Bunun neden olduğu hakkında herhangi bir fikriniz var mı (ya da nasıl sağlam bir şekilde kanıt yeniden yazımı yapabilirim)?


8
Biraz fazla beklemiyor musun? Eşitlik kanıtı üzerinde örüntü eşleştirme, (çift yönlü) bir eşitlik tesis etmektir. Hedef türüne nereye ve hangi yönde uygulanmasını istediğiniz hiç net değil. Örneğin, gelen symaramaları atlayabilirsiniz mulDistL've kodunuz yine de kontrol eder.
kosmikus

1
Büyük ihtimalle çok fazla şey bekliyorum. Bununla birlikte, çoğu durumda, aynı Agda'da olduğu gibi çalışır, bu nedenle, davranışın düzenlerini anlamak yine de yararlı olacaktır. Yine de iyimser değilim, çünkü mesele muhtemelen tip denetleyicinin bağırsaklarıyla derinden ilgili.
András Kovács

1
Bu, sorunuza göre biraz ortogonaldir, ancak bu ispatları Agda gibi bir dizi eşitlikçi muhakeme birleştiricisi kullanarak çıkarabilirsiniz. Cf. bu kavram kanıtı
gallais

Yanıtlar:


1

Bu tür olası tüm değerleri oluşturmak istiyorsanız, bunu yapmak için sağlanan veya belirtilen sınırlarla bir işlev yazabilirsiniz.

Bunların yaratılmasını sağlamak için tip düzeyinde Kilise Numaraları veya bazılarını kullanmak çok iyi olabilir, ancak muhtemelen istediğiniz / ihtiyacınız olan şey için neredeyse kesinlikle çok fazla iş.

İstediğiniz bu olmayabilir (yani "z = 5 - x - y'den beri sadece (x, y) kullanmak dışında"), ancak geçerli olmasına izin vermek için tür düzeyinde bir tür zorunlu kısıtlamaya sahip olmaya çalışmaktan daha mantıklıdır. değerler.


-3

Değerler çalışma zamanında belirlendiği için olur. Çalışma zamanında neyin girildiğine bağlı olarak değerlerin dönüşümünü sağlayabilir, dolayısıyla deliğin zaten güncellendiğini varsayar.


3
Elbette değerler çalışma zamanında belirlenir, ancak soruyla hiçbir ilgisi yoktur. Gerekli bilgiler zaten bir GADT'deki kalıp eşleştirmeden edinilebilir.
int_index
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.