为什么这个Agda程序不能在`with`子句下规范化表达式?

时间:2018-03-18 19:21:51

标签: agda

在以下的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 xtrue

1 个答案:

答案 0 :(得分:2)

模式匹配不会导致记住任何等同。匹配更新事物的值和类型:

  1. 在右侧的类型。
  2. 在左手边的其他论据中。
  3. 此更新发生在匹配点,并且不会进一步传递信息。在您的情况下,目标类型或其他参数中的任何内容都不依赖于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