Какими будут полезные рекомендации по преобразованию источника 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большую часть времени, поэтому это становится немного громоздким. Другой вариант состоит в том, чтобы извлечь тип в лемму и использоватьrewrites, однако это не всегда будет работать (например, когдаreplaceудаляет большую часть термина) -
destruct- если в одной переменной попробуйте расщепление в LHS, в противном случае используйте конструкциюwith -
induction- разделение на LHS и использование рекурсивного вызова вrewriteили непосредственно. Убедитесь, что по крайней мере один из аргументов в рекурсии структурно меньше, или вы терпите тотальность и не сможете использовать результат в качестве леммы. Для более сложных выражений вы также можете попробоватьSizeAccessibleизPrelude.WellFounded. -
trivial- как правило, как можно больше расщепляется в LHS и решает с помощьюRefls -
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