비정상적인 구멍 유형 해상도


105

최근에 증명에서 패턴 매칭과 결합 된 타입 홀이 Haskell에서 꽤 멋진 Agda와 같은 경험을 제공한다는 것을 알게되었습니다. 예를 들면 :

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

정말 좋은 점은 Refl -> exp구조 의 오른쪽을 유형 구멍 으로 대체 할 수 있고 구멍 대상 유형이 rewriteAgda 의 양식 과 거의 비슷하게 증명으로 업데이트된다는 것 입니다.

그러나 때때로 구멍이 업데이트되지 않습니다.

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

또한 대상 유형이 반드시 증명 내부에 정렬되는 것은 아니지만 Agda의 전체 내용을 붙여 넣으면 여전히 잘 확인됩니다.

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

왜 이런 일이 발생하는지 (또는 어떻게 확실한 방법으로 증명 재 작성을 할 수 있는지) 아이디어가 있습니까?


8
당신은 조금 많은 것을 기대하지 않습니까? 동등 증명에 대한 패턴 매칭은 (양방향) 동등성을 설정합니다. 대상 유형에 적용 할 위치와 방향이 명확하지 않습니다. 예를 들어, sym호출을 생략 할 수 mulDistL'있으며 코드는 계속 확인합니다.
kosmikus 2014

1
아마도 나는 너무 많은 것을 기대하고 있습니다. 그러나 대부분의 경우 Agda에서와 같이 작동하므로 동작의 규칙 성을 파악하는 것이 여전히 유용합니다. 문제가 유형 검사기의 장과 깊이 관련되어 있기 때문에 나는 낙관적이지 않습니다.
András Kovács 2014

1
귀하의 질문에 약간 직교하지만 Agda의 방정식 추론 결합자를 사용하여 이러한 증명을 가져올 수 있습니다. Cf. 개념의 증거
gallais

답변:


1

가능한 모든 값을 생성하려면 제공된 또는 지정된 경계를 사용하여 그렇게하는 함수를 작성할 수 있습니다.

유형 수준의 Church Numerals 또는 일부를 사용하여 이러한 생성을 강제하는 것이 가능할 수 있지만 아마도 원하는 / 필요한 것에 대해서는 거의 분명히 너무 많은 작업입니다.

이것은 당신이 원하는 것이 아닐 수도 있지만 (즉 "z = 5-x-y이기 때문에 (x, y) 만 사용하는 것을 제외하고") 유효를 허용하기 위해 유형 수준에 어떤 종류의 강제 제한을 두는 것보다 더 합리적입니다. 가치.


-3

값이 런타임에 결정되기 때문에 발생합니다. 런타임에 입력 된 내용에 따라 값이 변환 될 수 있으므로 구멍이 이미 업데이트되었다고 가정합니다.


3
물론 값은 런타임에 결정되지만 질문과 관련이 없습니다. 필요한 정보는 GADT의 패턴 일치에서 이미 사용할 수 있습니다.
int_index 2010 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.