I've uploaded a self-contained version of the code with all the right imports to make it easier for you to play with the code.
What's important here is to see the structure of the final vector you obtain when running allPairs
: you obtain m
chunks of size n
with a precise pattern.
The first chunk is listing the pairs composed of the head of xv
together with each one of the elements in yv
.
(...)
The nth chunk is listing the pairs composed of the nth element of xv
together with each one of the elements in yv
.
All these chunks are assembled by concatenation (_++_
). To be able to either select one chunk (because the x
you're looking for is in it) or skip it (because the x
is further away), you are therefore going to introduce intermediate theorems describing the interaction between _++_
and _∈_
.
You should be able to know how to select a chunk (in case x
is in this one) which corresponds to this easy intermediate lemma:
_∈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)
But you should also be able to skip a chunk (in case x
is further away) which corresponds to this other lemma:
_∈_++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)
Finally, once you have selected the right chunk, you can notice that it has been created using map
like so: Vec.map (λ y -> (x , y)) ys
. Well, one thing you can prove is that map
is compatible with membership proofs:
_∈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)
You can now put all of this together and produce the witness by induction on the proof that 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