Какими будут полезные рекомендации по преобразованию источника Coq в Idris (например, насколько похожи их системы типов и что можно сделать для перевода доказательств)? Из того, что я собираю, встроенная библиотека тактики Идриса минимальна, но расширяется, поэтому я полагаю, что с некоторой дополнительной работой это должно быть возможно.
Преобразование Coq в Idris
Ответ 1
Недавно я перевел фрагмент Software Foundations и сделал частичный порт {P | N | Z} Arith, некоторые наблюдения, которые я сделал в процессе:
Обычно использование тактики Idris (в форме Pruvloj
/Elab.Reflection
) на данный момент не рекомендуется, этот объект несколько хрупкий и довольно трудно отлаживать, когда что-то идет не так. Лучше использовать так называемый "стиль Агды", полагаясь, если это возможно, на соответствие шаблону. Вот несколько грубых эквивалентов для более простой тактики Coq:
-
intros
- просто укажите переменные на LHS -
reflexivity
-Refl
-
apply
- вызов функции напрямую -
simpl
- упрощение выполняется автоматически Idris -
unfold
- также автоматически выполняется для вас -
symmetry
-sym
-
congruence
/f_equal
-cong
-
split
- разделение на LHS -
rewrite
-rewrite ... in
-
rewrite <-
-rewrite sym $ ... in
-
rewrite in
- чтобы переписать внутри того, что у вас есть в качестве параметра, вы можете использовать конструкциюreplace {P=\x=>...} equation term
. К сожалению, Идрис не может вывестиP
большую часть времени, поэтому это становится немного громоздким. Другой вариант состоит в том, чтобы извлечь тип в лемму и использоватьrewrite
s, однако это не всегда будет работать (например, когдаreplace
удаляет большую часть термина) -
destruct
- если в одной переменной попробуйте расщепление в LHS, в противном случае используйте конструкциюwith
-
induction
- разделение на LHS и использование рекурсивного вызова вrewrite
или непосредственно. Убедитесь, что по крайней мере один из аргументов в рекурсии структурно меньше, или вы терпите тотальность и не сможете использовать результат в качестве леммы. Для более сложных выражений вы также можете попробоватьSizeAccessible
изPrelude.WellFounded
. -
trivial
- как правило, как можно больше расщепляется в LHS и решает с помощьюRefl
s -
assert
- лемма подwhere
-
exists
- зависимая пара(x ** prf)
-
case
- либоcase .. of
, либоwith
. Однако будьте осторожны сcase
- не используйте его во всем, о чем вы позже захотите узнать, иначе вы застрянете наrewrite
(см. вопрос № 4001). Обходным путем является создание верхнего уровня (в настоящее время вы не можете ссылаться на леммы вwhere
/with
, см. issue # 3991). -
revert
- "unintroduce" переменную, сделав лямбду и затем применив ее к указанной переменной -
inversion
- вручную определить и использовать тривиальные леммы о конструкторах:-- injectivity, used same as `cong`/`sym` FooInj : Foo a = Foo b -> a = b FooInj Refl = Refl -- disjointness, this sits in scope and is invoked when using `uninhabited`/`absurd` Uninhabited (Foo = Bar) where uninhabited Refl impossible