为什么具有摘要的agda不删除某些子句?

时间:2019-08-25 13:59:25

标签: with-statement agda unification

我正在尝试写一个由乌尔夫·诺雷尔(Ulf Norell)和詹姆斯·查普曼(James Chapman)(第23页)撰写的Dependently Typed Programming in Agda教程中作为练习的定理,而我对此并不了解。

基本上我有这些定义

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} -> (A -> Bool) -> A -> Set
satisfies p x = isTrue (p x)

data List (A : Set) : Set where
  []   : List A
  _::_ : (x : A)(xs : List A) -> List A

infixr 30 _:all:_
data All {A : Set} (P : A -> Set) : List A -> Set where
  all[]   : All P []
  _:all:_ : forall {x xs} -> P x -> All P xs -> All P (x :: xs)

filter : {A : Set} -> (A -> Bool) -> List A -> List A
filter p [] = []
filter p (x :: xs) with p x
... | true  = x :: filter p xs
... | false = filter p xs

我正在尝试解决这个问题

filter-all-lem : ∀ {p xs} -> All (satisfies p) (filter p xs)
filter-all-lem {p} {[]} with filter p []
... | [] = all[]
... | f :: fs = ?
filter-all-lem {p} {x :: xs} = ?

在第二个孔上,我还没有尝试过任何方法,这可能不是解决此问题的更好方法,但是我的问题不是这个。

filter p []是过滤器的第一种情况。它扩展为[]。那么,为什么agda无法推断出f :: fs的情况是不可能的?统一应该真的很容易解决这个问题。但是,如果我尝试完全删除该子句或使用荒谬的模式,则会收到错误消息,因为并未涵盖所有可能性。

如果agda的统一规则没有自动执行此操作,我如何强制其意识到这一点?也许重写? (我现在不知道如何在agda中重写)

1 个答案:

答案 0 :(得分:1)

在这种情况下不需要with filter p [],正如您所说,您已经可以推断出filter p [] = []。这样你就可以写

filter-all-lem {p} {[]} = all[]

为了理解子句,有助于了解Agda如何扩展这些子句(作为局部函数),其中匹配的事物(在这种情况下为filter p [])是一个新参数。所以你得到

filter-all-lem {p} {[]} = helper {p} (filter p [])
  where
  helper :: ∀ {p} ys -> All (satisfies p) ys
  helper [] = all[]
  helper (f :: fs) = ?

在帮助器内部,您实际上失去了该列表为空的知识。标准库中有检查惯用语,以等式形式保留这些知识,但是您在这里不需要。

作为证明与with(例如filter (x :: xs))一起使用的函数的事物的一般规则,您应在证明中的with子句或包含与之匹配的事物的子句具有完全相同的结构。依存类型。

相关问题