Types Agda:形成所有对{(x,y)| x in xs,y in ys}
我想知道在Agda中实现列表理解或笛卡尔积的最佳方法是什么 我有两个向量,Types Agda:形成所有对{(x,y)| x in xs,y in ys},types,functional-programming,agda,theorem-proving,dependent-type,Types,Functional Programming,Agda,Theorem Proving,Dependent Type,我想知道在Agda中实现列表理解或笛卡尔积的最佳方法是什么 我有两个向量,xs和ys。我想要(非正式的)集合{(x,y)| x in xs,y in 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 -
xs
和ys
。我想要(非正式的)集合{(x,y)| x in xs,y in 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
我不知道如何构造这样一个证人。据我所知,我失去了太多的向量的原始结构,无法使用归纳法
我在想
allPairs
时获得的最终向量的结构:获得具有精确模式的m
大小n
块
- 第一个区块列出了由
的头部以及xv
中的每个元素组成的对yv
- (……)
- 第n块列出了由
的第n个元素以及xv
中的每个元素组成的对yv
\uu++\uu
)来组装的。为了能够选择一个块(因为您要查找的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
另一种方法是将证据分成两部分。第一部分是x∈ xs->y∈ ys->(x,y)∈²xs×ys
,其中返回矩阵而不是向量。第二个是x∈²xss->x∈ concat xss
。两者都_∈_代码>和_∈²
可以用任何来表示,因此我认为还有进一步推广的余地。如果我在写一个库,我会选择这种方法,但对于简单的练习来说,这可能有些过头了。顺便说一句,解析包含ASCII符号序列的mixfix运算符并非易事,比如xs
in_∈map_xs
。我有点困惑。。。问题是什么∈ 在“有”的情况下两两如何?我以为它是一个类型构造函数,所以在值位置看到它时我很困惑。它来自这个mixfix标识符:_∈_++ys
。我试着给引理命名,强调它们正在做的事情,但是由于在SO中没有语法突出显示,所以很难阅读。我建议下载要点并在emacs中查看。如果你愿意,我也可以用重命名的引理编辑我的答案。