Recursion 理解Agda中关于FSA和正则语言的简单证明的递归调用失败
我试图证明Agda中的简单FSA只接受以零结尾的字符串——这是Sipser书中的第一个例子。我没有将evalFSA实现为一个谓词,而是一个函数,对于这是正确的还是错误的选择,我感到困惑,因为我现在很难证明机器和语言的可靠性和完整性结果,以及这个实现细节是否是我困难的原因 一旦我在下面的x上匹配了图案,它就会突出显示下面的蓝色线条。这意味着什么,它为什么这么做,为什么x0上的模式匹配解决了这个问题Recursion 理解Agda中关于FSA和正则语言的简单证明的递归调用失败,recursion,functional-programming,state-machine,regular-language,agda,Recursion,Functional Programming,State Machine,Regular Language,Agda,我试图证明Agda中的简单FSA只接受以零结尾的字符串——这是Sipser书中的第一个例子。我没有将evalFSA实现为一个谓词,而是一个函数,对于这是正确的还是错误的选择,我感到困惑,因为我现在很难证明机器和语言的可靠性和完整性结果,以及这个实现细节是否是我困难的原因 一旦我在下面的x上匹配了图案,它就会突出显示下面的蓝色线条。这意味着什么,它为什么这么做,为什么x0上的模式匹配解决了这个问题 soundM : (xs : List Σ') → evalFSA' M xs → endsIn0
soundM : (xs : List Σ') → evalFSA' M xs → endsIn0 xs
soundM (x ∷ []) evM = {!!}
soundM (x0 ∷ x1 ∷ xs) evM = {!!}
-- soundM (0' ∷ []) f = tt
这是最后一个问题。为什么我不能在1'的情况下应用递归调用?f之间的唯一区别是机器的当前使用状态和输入字符串,但显然这似乎是系统的对称性,不应影响我们的计算能力
soundM' : (xs : List Σ') → evalFSA' M xs → endsIn0 xs
soundM' (0' ∷ []) evM = tt
soundM' (0' ∷ x1 ∷ xs) f = soundM' (x1 ∷ xs) f
soundM' (1' ∷ x1 ∷ xs) f = soundM' {!!} f
以下是0'情况下的推断f:
f : modal.helper M 0' (x1 ∷ xs) M xs (δ' S₁ x1)
同样地,在1'的情况下:
f : modal.helper M 1' (x1 ∷ xs) M xs (δ' S₂ x1)
我同时也遇到了我所谓的完整性问题
completeM : (xs : List Σ') → endsIn0 xs → evalFSA' M xs ≡ ⊤
completeM (0' ∷ []) ex = refl
completeM (0' ∷ x1 ∷ xs) ex = completeM (x1 ∷ xs) ex
completeM (1' ∷ x1 ∷ xs) ex = {!!}
这是到达这里的代码
module fsa where
open import Bool
open import Level using (_⊔_)
open import Data.Nat.Base as Nat using (ℕ; zero; suc; _<′_; _+_)
open import Data.List.Base as List using (List; []; _∷_)
-- open import Data.Product as Prod using (∃; _×_; _,_)
open import Data.Empty
open import Data.Unit
open import Relation.Binary.PropositionalEquality using (_≡_; refl; subst)
-- open import Data.Fin as Fin
record FSA : Set₁ where
field
Q : Set
Σ : Set
δ : Q → Σ → Q
q₀ : Q
F : Q → Set
evalFSA' : (fsa : FSA) → List (FSA.Σ fsa) → Set
evalFSA' fsa [] = ⊥
evalFSA' fsa (x ∷ xs) = helper fsa (x ∷ xs) (FSA.q₀ fsa)
where
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)
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
FSA.Q M = Q'
FSA.Σ M = Σ'
FSA.δ M = δ'
FSA.q₀ M = q₀'
FSA.F M = F'
exF1 = evalFSA' M (0' ∷ [])
exF2 = evalFSA' M (1' ∷ (0' ∷ 0' ∷ 1' ∷ []))
-- a more general endIn that i was orignally trying to use, but likewise failed to get to work
data Dec (A : Set) : Set where
yes : A → Dec A
no : (A → ⊥) → Dec A
sigDec : (x y : Σ') → Dec (x ≡ y)
sigDec 0' 0' = yes refl
sigDec 0' 1' = no (λ ())
sigDec 1' 0' = no (λ ())
sigDec 1' 1' = yes refl
endsIn : {X : Set} → ((x y : X) → Dec (x ≡ y)) → List X → X → Set
endsIn d [] x = ⊥
endsIn d (x ∷ []) x0 with (d x0 x)
... | yes refl = ⊤
... | no x1 = ⊥
endsIn d (x ∷ x1 ∷ xs) x0 = endsIn d (x1 ∷ xs) x0
_endsIn'_ : List Σ' → Σ' → Set
xs endsIn' x = endsIn sigDec xs x
endsIn0 : List Σ' → Set
endsIn0 [] = ⊥
endsIn0 (0' ∷ []) = ⊤
endsIn0 (0' ∷ x ∷ xs) = endsIn0 (x ∷ xs)
endsIn0 (1' ∷ xs) = endsIn0 xs
-- testing
10endsin0 = (1' ∷ 0' ∷ []) endsIn' 0'
n10endsin0 = (1' ∷ 1' ∷ []) endsIn' 0'
你的帖子很大,包含很多元素,可以用不同的方式进行评论。我将逐一介绍它们,并解释我为使这些元素更容易访问而做的选择。请注意,这些选择包含在代码中的次要元素中,主要是外观元素,它们不会以任何方式更改定义的语义。首先,我将详细介绍正确的代码,然后回答问题 详细说明正确的代码 让我们首先将这些进口清理到所需的最低限度:
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
我已经从evalFSA函数中提取了你的helper函数。此更改的原因是,当使用when时,该函数将继承父函数的所有参数,这使得更难理解进一步的目标,例如modal.helper M 0'x1∷ xs M xsδS₁ x1
那么您的案例研究自动机保持不变,尽管我简化了记录实例化,但没有使用协同模式:
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
q₀' : Q'
q₀' = S₁
从这一点开始,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的定义中,正如我所解释的,我对其进行了更改
让我们考虑下面的代码,同时证明sOMM:
当询问Agda第一个目标中的目标和当前元素的类型时,它回答:Goal: helper M xs (δ' q₀' x)
Have: helper M xs (δ' S₁ x)
既然你已经定义了q₀' 详情如下:
endsWith0 : List Σ' → Set
endsWith0 [] = ⊥
endsWith0 (0' ∷ []) = ⊤
endsWith0 (_ ∷ xs) = endsWith0 xs
q₀' : Q'
q₀' = S₁
阿格达知道q₀' 定义上等于S₁ 这意味着当前术语实际上与目标具有相同的类型,这就是为什么它被接受的原因
但是,在另一个孔中,询问Agda相同的信息会给出:
Goal: helper M xs (δ' q₀' x)
Have: helper M xs (δ' S₂ x)
在这种情况下,q₀' 在定义上不等于S₂ 实际上,这意味着这些类型是不相等的,不可能马上得出结论
正如我的代码所示,模式匹配在x上的额外时间允许agda进一步减少目标,从而使我们能够得出结论
类似的推理也被用来证明你的文章非常大,包含了很多元素,所有这些元素都可以用不同的方式进行评论。我将逐一介绍它们,并解释我为使这些元素更容易访问而做的选择。请注意,这些选项包含代码中的次要元素,主要是外观元素,这些元素不会更改 在任何方面,你的定义的语义。首先,我将详细介绍正确的代码,然后回答问题 详细说明正确的代码 让我们首先将这些进口清理到所需的最低限度:
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
我已经从evalFSA函数中提取了你的helper函数。此更改的原因是,当使用when时,该函数将继承父函数的所有参数,这使得更难理解进一步的目标,例如modal.helper M 0'x1∷ xs M xsδS₁ x1
那么您的案例研究自动机保持不变,尽管我简化了记录实例化,但没有使用协同模式:
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
q₀' : Q'
q₀' = S₁
从这一点开始,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的定义中,正如我所解释的,我对其进行了更改
让我们考虑下面的代码,同时证明sOMM:
当询问Agda第一个目标中的目标和当前元素的类型时,它回答:Goal: helper M xs (δ' q₀' x)
Have: helper M xs (δ' S₁ x)
既然你已经定义了q₀' 详情如下:
endsWith0 : List Σ' → Set
endsWith0 [] = ⊥
endsWith0 (0' ∷ []) = ⊤
endsWith0 (_ ∷ xs) = endsWith0 xs
q₀' : Q'
q₀' = S₁
阿格达知道q₀' 定义上等于S₁ 这意味着当前术语实际上与目标具有相同的类型,这就是为什么它被接受的原因
但是,在另一个孔中,询问Agda相同的信息会给出:
Goal: helper M xs (δ' q₀' x)
Have: helper M xs (δ' S₂ x)
在这种情况下,q₀' 在定义上不等于S₂ 实际上,这意味着这些类型是不相等的,不可能马上得出结论
正如我的代码所示,模式匹配在x上的额外时间允许agda进一步减少目标,从而使我们能够得出结论
一个类似的推理被用来提供一个完整的证明