Agda - Интерактивное построение доказательств - Как использовать синтаксис дыр?

Извините за странное название, я понятия не имею, как на самом деле названы эти концепции.

Я слежу за Agdaучебник и есть раздел, объясняющий, как индуктивно строить доказательства: https://plfa.github.io/Induction/

Довольно здорово, что вы можете шаг за шагом расширять доказательство и получить дыру (это { }0) обновите его содержимое, чтобы сообщить вам, что происходит. Однако объясняется только, как это сделать при использованииrewrite синтаксис.

Как это работает, когда я хочу "вручную" провести доказательство в пределах begin блок, например:

+-assoc : ∀ (m n p : ℕ) → (m + n) + p ≡ m + (n + p)
+-assoc zero n p =
  begin
    (zero + n) + p
    ≡⟨⟩ n + p
    ≡⟨⟩ zero + (n + p)
  ∎
+-assoc (suc m) n p =
  begin
    (suc m + n) + p
    ≡⟨⟩ suc (m + n) + p
    ≡⟨⟩ suc ((m + n) + p)
    ≡⟨ cong suc (+-assoc m n p) ⟩
      suc (m + (n + p))
    ≡⟨⟩ suc m + (n + p)
  ∎

Проблема в следующем. Начнем с утверждения и начала доказательств:

+-assoc : ∀ (m n p : ℕ) → (m + n) + p ≡ m + (n + p)
+-assoc m n p = ?

Это оценивается как:

+-assoc : ∀ (m n p : ℕ) → (m + n) + p ≡ m + (n + p)
+-assoc m n p = { }0

В этом случае я хочу провести доказательство по индукции, поэтому я разделю их, используя C-c C-c используя переменную m:

+-assoc : ∀ (m n p : ℕ) → (m + n) + p ≡ m + (n + p)
+-assoc zero n p = { }0
+-assoc (suc m) n p = { }1

Базовый случай тривиален и заменяется на refl после разрешения с помощью C-c C-r. Однако индуктивный корпус (отверстие 1) требует доработки. Как я могу это повернуть{ }1 отверстие в следующей конструкции, чтобы провести доказательство:

begin
  -- my proof
  ∎

Мой редактор (spacemacs) говорит { }1только для чтения. Я не могу его удалить, только вставляю что-то между фигурными скобками. Я могу удалить его принудительно, но это явно не предназначено.

Что вы должны сделать, чтобы превратить дыру в beginблок? Что-то вроде этого

{ begin }1

не работает и приводит к сообщению об ошибке

Спасибо!

РЕДАКТИРОВАТЬ:

Итак, похоже, работает следующее:

{ begin ? }1

Это превращается в это:

+-assoc : ∀ (m n p : ℕ) → (m + n) + p ≡ m + (n + p)
+-assoc zero n p = refl
+-assoc (suc m) n p = begin { }0

Это прогресс:D. Но теперь я не могу понять, где поставить фактические шаги доказательства:

...
+-assoc (suc m) n p = begin (suc m + n) + p { }0
-- or
+-assoc (suc m) n p = begin { (suc m + n) + p }0

Ни один из них не работает

1 ответ

Решение

{ }1 только для чтения

Это сообщение отображается в двух случаях:

  • вы пытаетесь удалить дыру с помощью Backspace, что не сработает. Однако вы можете использовать C-backspace, если отверстие пусто
  • вы пытаетесь отредактировать пустое отверстие в режиме вставки / перезаписи, что тоже не сработает

Практическое правило: вы всегда очищаете отверстие с помощью C-c C-SPCс выражением типа, равного цели. В вашем случае это означает, что начинать сbegin ?, затем давая (suc m + n) + p ≡⟨⟩ ? и так далее.

Есть два способа улучшить отверстие:

  • C-c C-r: создает для вас новые дыры при задании функции. Например, с этой настройкой:

    test : Bool
    test = {!!}
    

    если вы напечатаете not в дыре

    test : Bool
    test = {!not!}
    

    и доработайте, вы получите

    test : Bool
    test = not {!!}
    

    т.е. новое отверстие создается автоматически для аргумента.

    Таким образом или исправляя дыру, Agda также переформатирует ваш код так, как ей нравится, что мне не нравится, поэтому я обычно не использую его.

  • C-c C-SPC: не создает новых дыр для аргументов и не переформатирует ваш код

Другие вопросы по тегам