Context free grammar 用CFG实例调试Agda中的约束满足错误
我试图实现Sipser计算理论中的第一个例子,得到一个无法辨认的黄色突出显示。在Agda中如何调试这些约束错误,在我的示例中如何调试?有没有什么成功的方法可以在第一时间避免它们<下面的代码>SipserExample1会产生这种混乱:Context free grammar 用CFG实例调试Agda中的约束满足错误,context-free-grammar,agda,Context Free Grammar,Agda,我试图实现Sipser计算理论中的第一个例子,得到一个无法辨认的黄色突出显示。在Agda中如何调试这些约束错误,在我的示例中如何调试?有没有什么成功的方法可以在第一时间避免它们SipserExample1会产生这种混乱: _r2_61 : rule Sipser1 [ at /home/wmacmil/agdaFall2019/constructiveTypeTheoriesNLSem/TT_course/agda_files/toy.agda:60,18-23 ] _r3_62 : rule
_r2_61 : rule Sipser1 [ at /home/wmacmil/agdaFall2019/constructiveTypeTheoriesNLSem/TT_course/agda_files/toy.agda:60,18-23 ]
_r3_62 : rule Sipser1 [ at /home/wmacmil/agdaFall2019/constructiveTypeTheoriesNLSem/TT_course/agda_files/toy.agda:60,18-23 ]
_r2_66 : rule Sipser1 [ at /home/wmacmil/agdaFall2019/constructiveTypeTheoriesNLSem/TT_course/agda_files/toy.agda:60,28-33 ]
_r3_67 : rule Sipser1 [ at /home/wmacmil/agdaFall2019/constructiveTypeTheoriesNLSem/TT_course/agda_files/toy.agda:60,28-33 ]
———— Errors ————————————————————————————————————————————————
Failed to solve the following constraints:
_r2_66 ++ inj₁ A0 ∷ _r3_67 = inj₁ A0 ∷ []
: List (CFG.V Sipser1 ⊎ CFG.Σ' Sipser1)
(blocked on _r2_66)
_r2_66 ++ (inj₁ B0 ∷ []) ++ _r3_67 = _r2_61 ++ inj₁ A0 ∷ _r3_62
: List (CFG.V Sipser1 ⊎ CFG.Σ' Sipser1)
(blocked on any(_r2_61, _r3_62, _r2_66, _r3_67))
_r2_61 ++ (inj₁ B0 ∷ []) ++ _r3_62
= inj₂ a0 ∷ map inj₂ (a0 ∷ a# ∷ a1 ∷ a1 ∷ [])
: List (CFG.V Sipser1 ⊎ CFG.Σ' Sipser1)
(blocked on _r2_61)
下面是生成黄色的代码。CFG是一个简单的记录,我定义了终端和非终端列表上的manystep缩减关系<代码>生成只允许用户证明给定CFG允许一个终端列表
module toy where
open import Data.List
open import Data.Sum using (_⊎_ ; inj₁; inj₂)
open import Data.Product using (_×_; _,_)
open import Data.Unit
open import Data.Empty
binRel : Set → Set → Set₁
binRel A B = A → B → Set
record CFG : Set₁ where
field
V : Set -- non-terminal, or variable
Σ' : Set -- terminals
R : binRel V (List (V ⊎ Σ'))-- rules
S : V -- start symbol
module ManyStep where
open CFG
rule : CFG → Set
rule cfg = List (V cfg ⊎ Σ' cfg)
data ↦* (cfg : CFG) : rule cfg → rule cfg → Set where
refl : {r : (rule cfg)} → ↦* cfg r r --∀ {σ : Σ' cfg} → {!!}
trans : {r1 r2 r3 : (rule cfg)} {v : V cfg} {X : (rule cfg)} → R cfg v X
→ ↦* cfg r1 (r2 ++ (inj₁ v) ∷ r3)
→ ↦* cfg r1 (r2 ++ X ++ r3)
derives : (cfg : CFG) → rule cfg → Set
derives cfg x = ↦* cfg (inj₁ (S cfg) ∷ []) x
generates : (cfg : CFG) → List (Σ' cfg) → Set
generates cfg xs = derives cfg (map inj₂ xs)
open ManyStep public
data V0 : Set where
A0 : V0
B0 : V0
data Σ0 : Set where
a0 : Σ0
a1 : Σ0
a# : Σ0
data _⟶_ : V0 → List (V0 ⊎ Σ0) → Set where
r0 : A0 ⟶ (inj₂ a0 ∷ inj₁ A0 ∷ inj₂ a1 ∷ [])
r1 : A0 ⟶ (inj₁ B0 ∷ [])
r2 : B0 ⟶ (inj₂ a# ∷ [])
Sipser1 : CFG
Sipser1 = record { V = V0 ; Σ' = Σ0 ; R = _⟶_ ; S = A0 }
SipserExample1 : generates Sipser1 (a0 ∷ a0 ∷ a# ∷ a1 ∷ a1 ∷ [])
SipserExample1 = trans r1 (trans r1 (refl {Sipser1} {inj₁ A0 ∷ []}))
-----编辑-----
根据@Jesper的一些见解,正确的解决方案实际上是:
SipserExample1 : generates Sipser1 (a0 ∷ a0 ∷ a# ∷ a1 ∷ a1 ∷ [])
SipserExample1 = trans {r2 = inj₂ a0 ∷ inj₂ a0 ∷ []} {r3 = inj₂ a1 ∷ inj₂ a1 ∷ []} r2
(trans {r2 = inj₂ a0 ∷ inj₂ a0 ∷ []} {r3 = inj₂ a1 ∷ inj₂ a1 ∷ []} r1
(trans {r2 = inj₂ a0 ∷ []} {r3 = inj₂ a1 ∷ []} r0
(trans {r2 = []} {r3 = []} r0 refl)))
我解决这类问题的策略是,首先忽略未解决的约束,而尝试帮助Agda填充未解决的元变量,在您的案例中,是以下部分:
_r2_61 : rule Sipser1 [ at /home/wmacmil/agdaFall2019/constructiveTypeTheoriesNLSem/TT_course/agda_files/toy.agda:60,18-23 ]
_r3_62 : rule Sipser1 [ at /home/wmacmil/agdaFall2019/constructiveTypeTheoriesNLSem/TT_course/agda_files/toy.agda:60,18-23 ]
_r2_66 : rule Sipser1 [ at /home/wmacmil/agdaFall2019/constructiveTypeTheoriesNLSem/TT_course/agda_files/toy.agda:60,28-33 ]
_r3_67 : rule Sipser1 [ at /home/wmacmil/agdaFall2019/constructiveTypeTheoriesNLSem/TT_course/agda_files/toy.agda:60,28-33 ]
这些元变量的名称及其位置为您提供了一个很好的线索:它们是对SipserExample1
主体中的trans
函数的第一次和第二次调用的第二个和第三个隐式参数。下一步是使这些隐式参数显式化:在调用trans后写入{r2=?}{r3=?}
,重新加载文件,并尝试填充这些孔,直到约束消失或得到正确的错误消息
PS:通常人们更喜欢用等式推理的方式来写这类证明(参见例),这会迫使你在这种情况下解释出隐含的论点。谢谢。在上面的正确解决方案中,我发现在编写解决方案时,所需的
{r2=?}{r3=?}
元变量可以通过
解决,除了空列表(trans'{r2=[]}{r3=[]}r0 refl'))
需要人工实例化的情况。为什么打字员不能推断出这种情况?此外,为什么一旦提供了值,即使可以推断,仍然需要提供r2
和r3
值?有没有办法简化过程,使证明看起来更清晰,更容易编写一些等式推理语法糖的模块?Agda无法推断最后调用trans
的r2
和r3
的原因是,它不是一个中性术语:它可以简化为r0
。Agda typechecker(以及通常的双向typechecker)不能很好地推断没有注释的非中性术语的类型。我没有一个很好的方法来简化这个过程,我通常会添加很多隐式参数,直到所有问题都解决了,然后再看看哪些参数可以被删除,而不是破坏它。