Ваш пост очень большой и содержит множество элементов, которые можно комментировать по-разному. Я обращусь к ним один за другим и объясню, что сделал, чтобы сделать эти элементы более доступными. Обратите внимание, что этот выбор состоит из второстепенных элементов в ваших кодах, в основном cosmeti c, которые никоим образом не меняют семантику ваших определений. Я начну с того, что дам вам правильный код в деталях, после чего я отвечу на вопросы.
Детальный правильный код
Давайте начнем с очистки этого импорта до минимально необходимого :
module FSA where
open import Data.List.Base
open import Data.Empty
open import Data.Unit
Затем я сохранил ваше определение вашей записи автомата:
record FSA : Set₁ where
field
Q : Set
Σ : Set
δ : Q → Σ → Q
q₀ : Q
F : Q → Set
Я извлек вашу функцию helper
из функции evalFSA'
. Причина этого изменения заключается в том, что при использовании when
функция наследует все параметры от родительской функции, что затрудняет понимание дальнейших целей, таких как modal.helper M 0' (x1 ∷ xs) M xs (δ' S₁ x1)
.
helper : (fsa : FSA) → List (FSA.Σ fsa) → (FSA.Q fsa) → Set
helper fsa [] q = FSA.F fsa q
helper fsa (x ∷ xs) q = helper fsa xs ((FSA.δ fsa) q x)
evalFSA' : (fsa : FSA) → List (FSA.Σ fsa) → Set
evalFSA' fsa [] = ⊥
evalFSA' fsa (x ∷ xs) = helper fsa (x ∷ xs) (FSA.q₀ fsa)
Тогда ваш случай автомат исследования остался прежним, хотя я упростил создание экземпляра записи без использования копа-шаблонов:
data Q' : Set where
S₁ : Q'
S₂ : Q'
data Σ' : Set where
0' : Σ'
1' : Σ'
q₀' : Q'
q₀' = S₁
F' : Q' → Set
F' S₁ = ⊤
F' S₂ = ⊥
δ' : Q' → Σ' → Q'
δ' S₁ 0' = S₁
δ' S₁ 1' = S₂
δ' S₂ 0' = S₁
δ' S₂ 1' = S₂
M : FSA
M = record { Q = Q' ; Σ = Σ' ; δ = δ' ; q₀ = q₀' ; F = F' }
Я также упростил ваш предикат endsWith0
следующим образом:
endsWith0 : List Σ' → Set
endsWith0 [] = ⊥
endsWith0 (0' ∷ []) = ⊤
endsWith0 (_ ∷ xs) = endsWith0 xs
С этого момента soundM
и completeM
доказываются следующим образом (я усреднил их подписи):
soundM : ∀ xs → evalFSA' M xs → endsWith0 xs
soundM (0' ∷ []) evM = evM
soundM (0' ∷ x₁ ∷ xs) evM = soundM (x₁ ∷ xs) evM
soundM (1' ∷ 0' ∷ xs) evM = soundM (0' ∷ xs) evM
soundM (1' ∷ 1' ∷ xs) evM = soundM (1' ∷ xs) evM
completeM : ∀ xs → endsWith0 xs → evalFSA' M xs
completeM (0' ∷ []) ex = ex
completeM (0' ∷ x₁ ∷ xs) = completeM (x₁ ∷ xs)
completeM (1' ∷ 0' ∷ xs) = completeM (0' ∷ xs)
completeM (1' ∷ 1' ∷ xs) = completeM (1' ∷ xs)
Ответы на вопросы, не связанные с доказательством
- О предикатах и функциях возвращая типы, вы спросили:
Я реализовал evalFSA не как предикат, а как функцию, и меня смущает, было ли это правильным или неправильным выбором
На этот вопрос нет хорошего ответа. Обе идеи возможны, и на этом сайте часто обсуждаются другие вопросы. Я лично всегда использую предикаты, когда это возможно, но у других есть аргументы в пользу функций, возвращающих ⊤
или ⊥
. И, как вы заметили, можно доказать, что вы хотели, используя свою реализацию.
О странном выделении, вы спросили:
он выделяет строку ниже синим цветом. что это значит
Насколько я знаю, это баг. Какая-то странная окраска, подобная этой, стала иногда случаться и со мной в последнее время, но они, видимо, ничего не значат.
Ответьте на ваш вопрос, связанный с проверкой
Вы задали следующий вопрос:
почему я не могу применить рекурсивный вызов в 1 ' кейс? единственное различие между f - это текущее состояние машины и входной строки, но очевидно, что это похоже на симметрию системы, которая не должна влиять на нашу способность вычислять
Ответ на этот вопрос на самом деле довольно прост, но этот ответ был несколько скрыт в вашей реализации, потому что вы встроили определение helper
внутри определения evalFSA'
, которое я изменил, как описано.
Давайте рассмотрим следующий код, пока soundM
:
soundM : (xs : List Σ') → evalFSA' M xs → endsWith0 xs
soundM (0' ∷ []) evM = evM
soundM (0' ∷ x ∷ xs) evM = soundM (x ∷ xs) {!evM!}
soundM (1' ∷ x ∷ xs) evM = soundM (x ∷ xs) {!evM!}
На вопрос Agda, какова цель и тип текущего элемента в первой цели, она отвечает:
Goal: helper M xs (δ' q₀' x)
Have: helper M xs (δ' S₁ x)
Поскольку вы определили q₀'
следующим образом:
q₀' : Q'
q₀' = S₁
Agda знает, что q₀'
по определению равно S₁
, что означает, что текущий термин фактически имеет тот же тип, что и цель, поэтому он принят.
В другом отверстии, однако, запрос Agda той же информации дает:
Goal: helper M xs (δ' q₀' x)
Have: helper M xs (δ' S₂ x)
В этом случае q₀'
по определению не является e qual to S₂
(и на самом деле не равны), что означает, что эти типы не равны, и невозможно сразу сделать вывод.
Как показано в моем коде, сопоставление с образцом в x
позволяет agda еще больше уменьшить цель, что позволяет нам сделать вывод.
Аналогичное рассуждение используется для доказательства completeM