如何说服Agda函数在一对内部以减少的数字终止?

时间:2019-04-04 15:32:39

标签: agda

我正在为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ᴴᴸ

并相应地更改了功能;但这不能解决问题。

我如何说服阿格达这个功能(以及其他使用相同想法的类似功能)将终止? (理想情况下,无需过多修改数据类型。)

1 个答案:

答案 0 :(得分:2)

您对两个参数进行结构递归:表达式的结构和加油。有时燃料下降,有时表情下降,但并非其他情况保持不变。这通常不会终止。您只能沿着订单的词汇积进行递归。