阿格达:形成所有对{(x,y)| xs中的x,ys中的y}

时间:2015-07-13 22:15:10

标签: types functional-programming agda theorem-proving dependent-type

我想知道在Agda中处理列表推导或笛卡尔产品的最佳方法是什么。

我所拥有的是两个向量,xsys。我想要(非正式)集合{(x,y)| x在xs中,y在ys中。

我可以使用map和concat很容易地形成这个集合:

allPairs :  {A : Set} -> {m n : ℕ} -> Vec A m -> Vec A n -> Vec (A × A) (m * n)
allPairs xs ys = Data.Vec.concat (Data.Vec.map (λ x -> Data.Vec.map (λ y -> (x , y) ) ys  ) xs )

从这里开始,我喜欢为双人作见证,比如:

pairWitness : ∀ {A} -> {m n : ℕ} -> (xv : Vec A m) -> (yv : Vec A n) -> (x : A) -> (y : A) -> x ∈ xv -> y ∈ yv -> (x , y ) ∈ allPairs xv yv

我不知道如何建造这样的证人。据我所知,我失去了太多的矢量原始结构,以便能够使用我的归纳案例。

我想知道

  1. 标准库中有什么东西可以处理这种"所有对"操作,那已经有证据证明是这样的吗?
  2. 如果没有,我该如何构建对证人?

1 个答案:

答案 0 :(得分:4)

我已使用所有正确的导入上传a self-contained version of the code,以便您更轻松地使用代码。

这里重要的是查看运行allPairs时获得的最终向量的结构:您获得具有精确模式的m大小为n的块。< / p>

  • 第一个块列出由xv的头部组成的对以及yv中的每个元素。

  • (...)

  • 第n个块列出了由xv的第n个元素组成的对以及yv中的每个元素。

所有这些块都是通过连接(_++_)组装的。为了能够选择一个块(因为你要查找的x)或跳过它(因为x更远),你将引入中间体描述_++__∈_之间相互作用的定理。

你应该能够知道如何选择一个块(如果x在这个中),这对应于这个简单的中间引理:

_∈xs++_ : {A : Set} {x : A} {m : ℕ} {xs : Vec A m}
          (prx : x ∈ xs) {n : ℕ} (ys : Vec A n) → x ∈ xs ++ ys
here     ∈xs++ ys = here
there pr ∈xs++ ys = there (pr ∈xs++ ys)

但是你也应该能够跳过一个块(如果x离得更远),这对应于另一个引理:

_∈_++ys : {A : Set} {x : A} {n : ℕ} {ys : Vec A n}
          (prx : x ∈ ys) {m : ℕ} (xs : Vec A m) → x ∈ xs ++ ys
pr ∈ []     ++ys = pr
pr ∈ x ∷ xs ++ys = there (pr ∈ xs ++ys)

最后,一旦选择了正确的块,您可以注意到它是使用map创建的,如下所示:Vec.map (λ y -> (x , y)) ys。好吧,您可以证明的一点是map与会员证明兼容:

_∈map_xs : {A B : Set} {x : A} {m : ℕ} {xs : Vec A m}
           (prx : x ∈ xs) (f : A → B) → f x ∈ Vec.map f xs
here     ∈map f xs = here
there pr ∈map f xs = there (pr ∈map f xs)

现在,您可以将所有这些放在一起,并通过感应来证明x ∈ xs

pairWitness : {A : Set} {m n : ℕ} (xv : Vec A m) (yv : Vec A n)
              {x y : A} -> x ∈ xv -> y ∈ yv -> (x , y) ∈ allPairs xv yv
pairWitness (x ∷ xv) yv here  pry = pry ∈map (λ y → x , y) xs ∈xs++ allPairs xv yv
pairWitness (x ∷ xv) yv (there prx) pry = pairWitness _ _ prx pry ∈ Vec.map (λ y → x , y) yv ++ys