我正在为Agda中的编译器的代码生成部分编码并证明其正确性。我很难说服Agda我的某些功能终止了。我正在使用的高级语言具有while循环,因此显然对于任何给定程序都无法保证终止。
因此,我使用的是“加油”变量,它只是一个自然数,在执行每个表达式时减1,从而限制了程序可以运行的步骤数。
我很满意这可以保证终止合同,但是阿格达并不那么容易相信。
data Stateᴴᴸ : Set where
stateᴴᴸ : Store → (fuel : ℕ) → Stateᴴᴸ
{-# TERMINATING #-}
storeᴴᴸ' : IExp → Stateᴴᴸ → Stateᴴᴸ
storeᴴᴸ' i (stateᴴᴸ σ 0) = stateᴴᴸ σ 0
storeᴴᴸ' SKIP (stateᴴᴸ σ (suc f)) = stateᴴᴸ σ f
storeᴴᴸ' (x ≔ a) (stateᴴᴸ σ (suc f)) = stateᴴᴸ ((x ≔ aexe a σ) ∷ σ) f
storeᴴᴸ' (P ⋯ Q) state = storeᴴᴸ' Q (storeᴴᴸ' P state)
storeᴴᴸ' (IF b THEN P ELSE Q) (stateᴴᴸ σ (suc f)) with bexe b σ
... | true = storeᴴᴸ' P (stateᴴᴸ σ f)
... | false = storeᴴᴸ' Q (stateᴴᴸ σ f)
storeᴴᴸ' (WHILE b DO c) (stateᴴᴸ σ (suc f)) with bexe b σ
... | true = storeᴴᴸ' (c ⋯ (WHILE b DO c)) (stateᴴᴸ σ f)
... | false = stateᴴᴸ σ f
在上面的代码中,我必须使用终止编译指示,否则Agda会提出以下投诉:
Termination checking failed for the following functions:
storeᴴᴸ'
Problematic calls:
storeᴴᴸ' Q (storeᴴᴸ' P state)
storeᴴᴸ' P state
storeᴴᴸ' (c ⋯ (WHILE b DO c)) (stateᴴᴸ σ f)
最初,我认为这是因为我的Stateᴴᴸ
数据类型不具有ℕ
的递归结构。所以我将其修改为以下内容:
data Stateᴴᴸ : Set where
stateᴴᴸ : Store → Stateᴴᴸ
sucstateᴴᴸ : Stateᴴᴸ → Stateᴴᴸ
并相应地更改了功能;但这不能解决问题。
我如何说服阿格达这个功能(以及其他使用相同想法的类似功能)将终止? (理想情况下,无需过多修改数据类型。)
答案 0 :(得分:2)
您对两个参数进行结构递归:表达式的结构和加油。有时燃料下降,有时表情下降,但并非其他情况保持不变。这通常不会终止。您只能沿着订单的词汇积进行递归。