在以下的Agda计划中:
module Hello where
data False : Set where
record True : Set where
data Bool : Set where
true : Bool
false : Bool
isTrue : Bool -> Set
isTrue true = True
isTrue false = False
satisfies : {A : Set} -> (p : A -> Bool) -> (x : A) -> Set
satisfies p x = isTrue (p x)
data List (a : Set) : Set where
[] : List a
_::_ : a -> List a -> List a
filter : {A : Set} -> (A -> Bool) -> List A -> List A
filter p [] = []
filter p (x :: xs) with p x
... | false = filter p xs
... | true = x :: filter p xs
data All {A : Set}(P : A -> Set) : List A -> Set where
vacuo : All P []
holds : (x : A) -> (xs : List A) -> P x -> All P xs -> All P (x :: xs)
filter-lem-b : {A : Set} -> (p : A -> Bool) -> (xs : List A) -> All (satisfies p) (filter p xs)
filter-lem-b p [] = vacuo
filter-lem-b p (x :: xs) with p x
filter-lem-b p (x :: xs) | true = let u = holds {P = satisfies p} x xs in ?
filter-lem-b p (x :: xs) | false = filter-lem-b p xs
洞的背景说:
u : isTrue (p x) →
All (λ x₁ → isTrue (p x₁)) xs →
All (λ x₁ → isTrue (p x₁)) (x :: xs)
为什么没有isTrue (p x)
缩减为True
,因为在匹配的分支上,已经确定p x
是true
?
答案 0 :(得分:2)
模式匹配不会导致记住任何等同。匹配更新事物的值和类型:
此更新发生在匹配点,并且不会进一步传递信息。在您的情况下,目标类型或其他参数中的任何内容都不依赖于p x
,因此当您匹配时不会更新任何内容。
一种解决方案是使用inspect
,它会记住证明某个审核员等于该模式的证据:
open import Relation.Binary.PropositionalEquality
filter-lem-b : {A : Set} -> (p : A -> Bool) -> (xs : List A) -> All (satisfies p) (filter p xs)
filter-lem-b p [] = vacuo
filter-lem-b p (x :: xs) with p x | inspect p x
... | true | [ eq ] = holds _ _ (subst isTrue (sym eq) _) (filter-lem-b p xs)
... | false | [ eq ] = filter-lem-b p xs