idris - 根据(进一步)证明证明类型的相等性

标签 idris dependent-type

假设我们想要一个“正确的”minusNat s,要求m <= n对于 n `minus` m有意义:

%hide minus

minus : (n, m : Nat) -> { auto prf : m `LTE` n } -> Nat
minus { prf = LTEZero } n Z = n
minus { prf = LTESucc prevPrf } (S n) (S m) = minus n m

现在让我们尝试证明以下引理,指出 (n + (1 + m)) - k = ((1 + n) + m) - k ,假设双方都有效:

minusPlusTossS : (n, m, k : Nat) ->
                 { auto prf1 : k `LTE` n + S m } ->
                 { auto prf2 : k `LTE` S n + m } ->
                 minus (n + S m) k = minus (S n + m) k

该目标表明以下困境可能有所帮助:

plusTossS : (n, m : Nat) -> n + S m = S n + m
plusTossS Z m = Refl
plusTossS (S n) m = cong $ plusTossS n m

所以我们尝试使用它:

minusPlusTossS n m k =
  let tossPrf = plusTossS n m
  in rewrite tossPrf in ?rhs

我们失败了:

When checking right hand side of minusPlusTossS with expected type
        minus (n + S m) k = minus (S n + m) k

When checking argument prf to function Main.minus:
        Type mismatch between
                LTE k (S n + m) (Type of prf2)
        and
                LTE k replaced (Expected type)

        Specifically:
                Type mismatch between
                        S (plus n m)
                and
                        replaced

如果我正确理解这个错误,它只是意味着它尝试将目标相等的 RHS (即 minus { prf = prf2 } (S n + m) k )重写为 minus { prf = prf2 } (n + S m) k并失败了。当然,因为 prf是不同不等式的证明!而同时replace可用于生成 (S n + m) k 的证明(或者 prf1 也可以),看起来不可能同时重写和更改证明对象以使其与重写相匹配。

我该如何解决这个问题?或者,更一般地说,我如何证明这个引理?

最佳答案

好吧,我想我已经解决了。底线:如果你不知道该怎么做,就做一个引理!

因此,我们有两个被减数 n1, n2 相等的证明,并且我们需要生成 n1 `minus` m = n2 `minus` m 的证明。让我们把它写下来!

minusReflLeft : { n1, n2, m : Nat } -> (prf : n1 = n2) -> (prf_n1 : m `LTE` n1) -> (prf_n2 : m `LTE` n2) -> n1 `minus` m = n2 `minus` m
minusReflLeft Refl LTEZero LTEZero = Refl
minusReflLeft Refl (LTESucc prev1) (LTESucc prev2) = minusReflLeft Refl prev1 prev2

我什至不再需要plusTossS,它可以用更直接适用的引理代替:

plusRightS : (n, m : Nat) -> n + S m = S (n + m)
plusRightS Z m = Refl
plusRightS (S n) m = cong $ plusRightS n m

之后,原来的就变得微不足道了:

minusPlusTossS : (n, m, k : Nat) ->
                 { auto prf1 : k `LTE` n + S m } ->
                 { auto prf2 : k `LTE` S n + m } ->
                 minus (n + S m) k = minus (S n + m) k
minusPlusTossS {prf1} {prf2} n m k = minusReflLeft (plusRightS n m) prf1 prf2

关于idris - 根据(进一步)证明证明类型的相等性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54913437/

相关文章:

lazy-evaluation - 我可以在 Idris 中证明 (s : Stream a) -> (head s::tail s = s) 吗?

haskell - 使用haskell的单例,如何编写 `fromList::[a] -> Vec a n` ?

coq - 如何在 Idris/Agda/Coq 中模式匹配多个值?

idris - (xs : Vect n elem) -> Vect (n * 2) elem

idris - 在 Refl 中使用重写

dependent-type - 在构造数据类型时选择类型类

idris - (\x=>2.0*x) `map` [1..10] "Can' t 找到 Enum Double 的实现”

parsing - Agda:解析嵌套列表

haskell - 编写与 GHC.Generics 一起使用的类型级函数

haskell - 如何在 Morte 中输入 zipWith?