Равенство между векторами одинаковой длины, но разной длины выражения в типе

#equality #idris #dependent-type

#равенство #идрис #зависимый тип

Вопрос:

Я занимаюсь некоторыми разработками в Идрисе и столкнулся со следующей проблемой. Допустим, у нас есть 3 вектора:

 xs : Vect len  a
ys : Vect len  a
zs : Vect len' a
 

и скажем, у нас тоже есть

 samelen : len = len' 
 

Наконец, мы также имеем следующие равенства:

 xsys : xs = ys

yszs : ys = zs
 

В первом равенстве мы имеем равенство для типа Vect len a, а во втором — для Vect len’a. Теперь мы хотим установить:

 xsza : xs = zs
 

Мне было нелегко заставить это работать. В частности, trans нуждается в равенстве между одними и теми же типами, но здесь это не так. Как здесь можно использовать транзитивность для достижения xsza?

Ответ №1:

Почему, конечно:

 xszs : {A : Type} -> {len, len' : Nat} ->
       (xs, ys : Vect len A) -> (zs : Vect len' A) ->
       len = len' ->
       xs = ys -> ys = zs ->
       xs = zs
xszs {A} {len} {len'=len} xs ys zs Refl = trans
 

Я думаю, важно знать, что это в основном должно быть функцией. Вы не можете использовать sameLen доказательство для замены len на len' в типах объектов, которые уже находятся в области видимости. То есть, если бы все ваши подписи типов были верхнего уровня, Idris никогда не смог бы в этом убедиться zs : Vect len a . Вы должны использовать вспомогательную функцию. В приведенной выше функции len' сопоставляется с len , оправдывается сопоставлением с Refl , перед введением zs переменной. Вы можете возразить, что это явно неверно, что zs и предшествует Refl аргументу, но, поскольку Idris — это общий язык, компилятору разрешено упростить вам жизнь, неявно переупорядочивая абстракцию, сопоставление и все такое прочее. По сути, непосредственно перед Refl сопоставлением, перед zs введением вводится тип цели (zs : Vect len' A) -> xs = ys -> ys = zs -> xs = zs , но совпадение переписывает его (zs : Vect len A) -> ?etc и zs вводится с более приятным типом.

Обратите внимание, что на len = len' самом деле это просто не нужно. Это работает:

 xszs : {A : Type} -> {len, len' : Nat} ->
       (xs, ys : Vect len A) -> (zs : Vect len' A) ->
       xs = ys -> ys = zs -> xs = zs
xszs {A} {len} {len'=len} xs xs xs Refl Refl = Refl
 

Или даже

 xszs : {A : Type} -> {len, len' : Nat} ->
       (xs, ys : Vect len A) -> (zs : Vect len' A) ->
       xs = ys -> ys = zs -> xs = zs
xszs xs ys zs = trans