当'b`已经匹配时证明`T b`

时间:2016-04-08 13:16:32

标签: boolean agda inspect

我试图证明一些简单的事情:

open import Data.List
open import Data.Nat
open import Data.Bool
open import Data.Bool.Properties
open import Relation.Binary.PropositionalEquality
open import Data.Unit

repeat : ∀ {a} {A : Set a} → ℕ → A → List A
repeat zero x = []
repeat (suc n) x = x ∷ repeat n x

filter-repeat : ∀ {a} {A : Set a} → (p : A → Bool) → (x : A) → T (p x) → ∀ n →
  filter p (repeat n x) ≡ repeat n x

我认为通过filter-repeat上的模式匹配证明p x会很容易:

filter-repeat p x prf zero = refl
filter-repeat p x prf (suc n) with p x
filter-repeat p x () (suc n) | false
filter-repeat p x prf (suc n) | true  = cong (_∷_ x) (filter-repeat p x prf n)

但是,这会抱怨prf : ⊤不属于T (p x)类型。所以我想,好吧,这似乎是一个熟悉的问题,让我们甩出inspect

filter-repeat p x prf zero = refl
filter-repeat p x prf (suc n) with p x | inspect p x
filter-repeat p x () (suc n) | false | _
filter-repeat p x tt (suc n) | true  | [ eq ] rewrite eq = cong (_∷_ x) (filter-repeat p x {!!} n)

但是尽管rewrite,洞的类型仍然是T (p x)而不是T true。这是为什么?如何将其类型缩减为T true,以便填写tt

解决方法

我可以使用T-≡

解决这个问题
open import Function.Equality using (_⟨$⟩_)
open import Function.Equivalence

filter-repeat : ∀ {a} {A : Set a} → (p : A → Bool) → (x : A) → T (p x) → ∀ n →
  filter p (repeat n x) ≡ repeat n x
filter-repeat p x prf zero = refl
filter-repeat p x prf (suc n) with p x | inspect p x
filter-repeat p x () (suc n) | false | _
filter-repeat p x tt (suc n) | true  | [ eq ] = cong (_∷_ x) (filter-repeat p x (Equivalence.from T-≡ ⟨$⟩ eq) n)

但我仍然想了解为什么基于inspect的解决方案无效。

2 个答案:

答案 0 :(得分:5)

正如AndrásKovács所说,归纳案例要求prfT (p x)类型,而您已通过模式匹配将其更改为 p x。一个简单的解决方案就是在filter-repeat上的模式匹配之前递归调用p x

open import Data.Empty

filter-repeat : ∀ {a} {A : Set a} → (p : A → Bool) → (x : A) → T (p x) → ∀ n →
  filter p (repeat n x) ≡ repeat n x
filter-repeat p x prf  0      = refl
filter-repeat p x prf (suc n) with filter-repeat p x prf n | p x
... | r | true  = cong (x ∷_) r
... | r | false = ⊥-elim prf

使用the protect pattern

有时也很有用
data Protect {a} {A : Set a} : A → Set where
  protect : ∀ x → Protect x

filter-repeat : ∀ {a} {A : Set a} → (p : A → Bool) → (x : A) → T (p x) → ∀ n →
  filter p (repeat n x) ≡ repeat n x
filter-repeat p x q  0      = refl
filter-repeat p x q (suc n) with protect q | p x | inspect p x
... | _ | true  | [ _ ] = cong (x ∷_) (filter-repeat p x q n)
... | _ | false | [ r ] = ⊥-elim (subst T r q)

protect q保存q的类型不会被重写,但这也意味着在false情况下,q的类型仍然是T (p x),因此额外的inspect

同一想法的另一个变体是

module _ {a} {A : Set a} (p : A → Bool) (x : A) (prf : T (p x)) where
  filter-repeat : ∀ n → filter p (repeat n x) ≡ repeat n x
  filter-repeat  0      = refl
  filter-repeat (suc n) with p x | inspect p x
  ... | true  | [ r ] = cong (x ∷_) (filter-repeat n)
  ... | false | [ r ] = ⊥-elim (subst T r prf)

module _ ... (prf : T (p x)) where也可以防止prf的类型被重写。

答案 1 :(得分:3)

依赖模式匹配仅在其使用的确切点影响目标和上下文。匹配p x会重写当前上下文,并将prf中的类型缩减为true

但是,当您执行递归filter-repeat调用时,您再次提供x作为参数,而T (p x)中的filter-repeat取决于 x,而不是外部环境中的旧的,即使它们在定义上是平等的。假设我们可以传递x以外的其他内容,因此在filter-repeat调用之前不能对它做出任何假设。

x可以通过从归纳中分解来使其在上下文中保持不变:

open import Data.Empty

filter-repeat : ∀ {a} {A : Set a} → (p : A → Bool) → (x : A) → T (p x) → ∀ n →
  filter p (repeat n x) ≡ repeat n x
filter-repeat p x prf = go where
  go : ∀ n → filter p (repeat n x) ≡ repeat n x
  go zero    = refl
  go (suc n) with p x | inspect p x
  go (suc n) | true  | [ eq ] = cong (_∷_ x) (go n)
  go (suc n) | false | [ eq ] = ⊥-elim (subst T eq prf)