with-statement - 为什么 agda with-abstract 不删除一些子句?

标签 with-statement agda unification

我正在尝试写一个定理,作为 Dependently Typed Programming in Agda 中的练习。 Ulf Norell 和 James Chapman 编写的教程(第 23 页),但我不明白有关 with 的一个可能非常简单的事情。

基本上我有这些定义

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[]是filter的第一种情况。它扩展为[]。那么为什么 agda 不能推断出 f::fs 的情况是不可能的呢?统一应该很容易解决这个问题。但是,如果我尝试完全删除该子句或使用荒谬的模式,我会收到错误,因为并未涵盖所有可能性。

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

最佳答案

在这种情况下不需要带有过滤器p []的,正如您所说,您已经可以推断出过滤器p [] = []。所以你可以直接写

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

为了理解 with 子句,它有助于了解 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 子句结构,或者with 子句包含依赖类型中匹配的事物。

关于with-statement - 为什么 agda with-abstract 不删除一些子句?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57646687/

相关文章:

agda - 使用 with-abstraction 的终止检查失败

c# - 类型参数统一

f# - 在F#中寻求统一算法

functional-programming - 自底向上 Hindley-Milner 类型推断 : Applying a substitution to an implicit constraint

python - 在上下文管理器 (with) 和异常处理程序中分配给具有 `as` 的成员

sql - WITH 是否创建一个临时表,如果可以,它可以安全地用于多个线程吗?

多行的 Python 嵌套上下文管理器

python - open 如何处理上下文管理?

haskell - 有效地抽象数据类型数量

agda - 抽象调用站点后终止检查器失败