Я не могу доказать (n - 0) = n с Идрисом
Я пытаюсь доказать, что на мой взгляд является разумной теоремой:
theorem1 : (n : Nat) -> (m : Nat) -> (n + (m - n)) = m
Доказательство индукцией доходит до точки, где мне нужно доказать это:
lemma1 : (n : Nat) -> (n - 0) = n
Вот что происходит, когда я пытаюсь доказать это (лемму, для простоты) с помощью интерактивного пословицы:
---------- Goal: ----------
{hole0} : (n : Nat) -> minus n 0 = n
> intros
---------- Other goals: ----------
{hole0}
---------- Assumptions: ----------
n : Nat
---------- Goal: ----------
{hole1} : minus n 0 = n
> trivial
Can't unify
n = n
with
minus n 0 = n
Specifically:
Can't unify
n
with
minus n 0
Мне показалось, что я что-то упустил в определении минуса, поэтому я поискал его в источнике:
||| Subtract natural numbers. If the second number is larger than the first, return 0.
total minus : Nat -> Nat -> Nat
minus Z right = Z
minus left Z = left
minus (S left) (S right) = minus left right
Определение, которое мне нужно, прямо здесь! minus left Z = left
. Насколько я понял, это был Идрис. следует просто заменить minus m 0
на m
здесь, и это тогда рефлексивно верно. Что я пропустил?4 ответа:
К сожалению, теорема, которую вы хотите доказать здесь, на самом деле не верна, потому что Idris naturals усекает вычитание при 0. Контрпример к вашему
theorem1
- этоn=3, m=0
. Давайте пройдем через оценку:Сначала подставим:
3 + (0 - 3) = 0
Далее мы десугарируем синтаксис к нижележащему экземпляру Num и помещаем в него собственно вызываемые функции:
plus (S (S (S Z))) (minus Z (S (S (S Z))))) = Z
Idris-это строгий язык вызовов по значениям, поэтому сначала мы оцениваем аргументы функций. Таким образом, мы уменьшите выражение
minus Z (S (S (S Z))))
. Глядя на определениеminus
, первый паттерн применим, потому что первый аргумент -Z
. Итак, мы имеем:plus (S (S (S Z))) Z = Z
plus
является рекурсивным по своему первому аргументу, поэтому следующий шаг вычисления дает:S (plus (S (S Z)) Z) = Z
Мы продолжаем этот путь до тех пор, пока
plus
не получитZ
в качестве своего первого аргумента, после чего он возвращает свой второй аргументZ
, давая тип:S (S (S Z)) = Z
Которого мы не можем построить жителя для.
Извините, если вышесказанное показалось немного педантичным и низкоуровневым, но очень важно учитывать конкретные шаги сокращения при работе с зависимыми типами. Это вычисления, которые вы получаете "бесплатно" внутри типов, поэтому хорошо организовать их так, чтобы они давали удобные результаты.
Однако решение Pdxleif, приведенное выше, хорошо работает для вашей леммы. Разбиение кейса на первый аргумент было необходимо, чтобы получить соответствие паттерна вminus
для работы. Помните, что она продолжается сверху вниз в шаблоне совпадений, и первый шаблон имеет конкретный конструктор на первом аргументе,что означает, что сокращение не может продолжаться, пока он не знает, соответствует ли этот конструктор.
Просто поиграл с интерактивным редактированием, сделал разбиение кейса и поиск доказательств, дает:
lemma1 : (n : Nat) -> (n - 0) = n lemma1 Z = refl lemma1 (S k) = refl
Это очевидно из определения минуса, поэтому оно просто refll. Может быть, он отказывался, когда входной var был просто n, потому что он мог бы иметь другое поведение, если бы это был Z или что-то еще? Или рекурсия?
На всякий случай, многие арифметические леммы уже определены в прелюдии Идриса, как и Ваша:
total minusZeroRight : (left : Nat) -> left - 0 = left minusZeroRight Z = refl minusZeroRight (S left) = refl
Для полноты картины (язык тактики был отвергнут в пользу рефлексии разработчика) я добавлю, что способ доказать вашу лемму на языке тактики-это вызвать
induction n
. Затем вы можете использоватьtrivial
, чтобы показать каждый случай (послеintros
в индуктивном случае).---------- Goal: ---------- {hole0} : (n : Nat) -> minus n 0 = n -lemma1> intros ---------- Other goals: ---------- {hole0} ---------- Assumptions: ---------- n : Nat ---------- Goal: ---------- {hole1} : minus n 0 = n -lemma1> induction n ---------- Other goals: ---------- elim_S0,{hole1},{hole0} ---------- Assumptions: ---------- n : Nat ---------- Goal: ---------- elim_Z0 : minus 0 0 = 0 -lemma1> trivial ---------- Other goals: ---------- {hole1},{hole0} ---------- Assumptions: ---------- n : Nat ---------- Goal: ---------- elim_S0 : (n__0 : Nat) -> (minus n__0 0 = n__0) -> minus (S n__0) 0 = S n__0 -lemma1> intros ---------- Other goals: ---------- {hole8},elim_S0,{hole1},{hole0} ---------- Assumptions: ---------- n : Nat n__0 : Nat ihn__0 : minus n__0 0 = n__0 ---------- Goal: ---------- {hole9} : minus (S n__0) 0 = S n__0 -lemma1> trivial lemma1: No more goals. -lemma1> qed Proof completed! lemma1 = proof intros induction n trivial intros trivial