Агда: формирование всех пар {(x, y) | х в хс, у в ys}

Мне интересно, как лучше всего подойти к спискам или декартовым продуктам в Agda.

У меня есть два вектора, xs и ys. Я хочу (неформальный) набор {(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. Если нет, то как мне создать пару свидетелей?

person jmite    schedule 13.07.2015    source источник


Ответы (1)


Я загрузил автономную версию кода со всеми нужными импортами, чтобы упростить для вас, чтобы играть с кодом.

Здесь важно увидеть структуру конечного вектора, который вы получите при запуске allPairs: вы получите m фрагментов размера n с точным шаблоном.

  • В первом фрагменте перечислены пары, состоящие из головы xv вместе с каждым из элементов yv.

  • (...)

  • N-й блок содержит пары, состоящие из n-го элемента xv вместе с каждым из элементов 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
person gallais    schedule 14.07.2015
comment
Еще один способ — разбить доказательство на две части. Первая часть — x ∈ xs -> y ∈ ys -> (x , y) ∈² xs ײ ys, где _ײ_ возвращает матрицу вместо вектора. Второй x ∈² xss -> x ∈ concat xss. И _∈_, и _∈²_ могут быть представлены в терминах Any, поэтому я полагаю, что есть возможность для дальнейшего обобщения. Если бы я писал библиотеку, я бы выбрал этот подход, но для простых упражнений это, вероятно, излишне. Кстати, не так просто разобрать операторы миксфиксов, которые содержат последовательности символов ASCII, например xs в _∈map_xs. - person user3237465; 14.07.2015
comment
Я немного запутался... что делает ∈ в случае с pairWitness? Я думал, что это конструктор типа, поэтому я сбит с толку, увидев его в позиции значения. - person jmite; 14.07.2015
comment
Это происходит от этого идентификатора миксфикса: _∈_++ys. Я пытался дать имена леммам, подчеркивая, что они делают, но отсутствие подсветки синтаксиса в SO затрудняет чтение. Я бы предложил скачать суть и посмотреть на нее в emacs. Или я мог бы отредактировать свой ответ с переименованными леммами, если хотите. - person gallais; 14.07.2015