我有一个简单的归纳记录,其中一个字段是求和类型。 Unit
为我们提供了一种简单的玩法。
open import Data.Maybe
open import Data.Sum
data Unit : Set where
unit : Unit
record Stream : Set where
coinductive
field
step : Unit ⊎ Stream
open Stream
valid
通过终止检查器:
valid : Maybe Unit → Stream
step (valid x) = inj₂ (valid x)
但是说我想消除Maybe Unit
成员,只有在拥有just
时递归。
invalid₀ : Maybe Unit → Stream
step (invalid₀ x) = maybe (λ _ → inj₂ (invalid₀ x)) (inj₁ unit) x
现在终止检查器不满意!
Termination checking failed for the following functions:
invalid₀
Problematic calls:
invalid₀ x
为什么这不能满足终止检查器?有没有解决的办法,或者我的概念理解不正确?
agda --version
产生Agda version 2.6.0-7ae3882
。我仅使用默认选项进行编译。
-v term:100
的输出在这里:https://gist.github.com/emilyhorsman/f6562489b82624a5644ed78b21366239
Agda version 2.5.4.2
。无法解决。--termination-depth=10
。无法解决。答案 0 :(得分:5)
您可以在此处使用sized types。
open import Data.Maybe
open import Data.Sum
open import Size
data Unit : Set where
unit : Unit
record Stream {i : Size} : Set where
coinductive
field
step : {j : Size< i} → Unit ⊎ Stream {j}
open Stream
valid : Maybe Unit → Stream
step (valid x) = inj₂ (valid x)
invalid₀ : {i : Size} → Maybe Unit → Stream {i}
step (invalid₀ x) = maybe (λ _ → inj₂ (invalid₀ x)) (inj₁ unit) x
_ : step (invalid₀ (nothing)) ≡ inj₁ unit
_ = refl
_ : step (invalid₀ (just unit)) ≡ inj₂ (invalid₀ (just unit))
_ = refl
在Size
的定义中更明确地说明invalid₀
参数:
step (invalid₀ {i} x) {j} = maybe (λ _ → inj₂ (invalid₀ {j} x)) (inj₁ unit) x
其中j
的类型为Size< i
,因此对invalid₀
的递归调用位于“较小”的Size
上。
请注意,valid
不需要任何“帮助”即可通过终止检查,完全不需要推理Size
。
答案 1 :(得分:3)
问题在于,阿格达(Agda)无法看到invalid₀
具有生产力。这是因为它既递归又不受构造函数的保护。在确定是否终止时,Agda不会查看maybe
的定义。
这是一个满足终止检查器的实现,因为两个分支都由构造函数和/或非递归保护:
okay₀ : Maybe Unit → Stream
step (okay₀ x@(just _)) = inj₂ (invalid₀ x)
step (okay₀ nothing) = inj₁ unit
重要的是递归just
的情况下,构造函数inj₂
作为表达式的顶层。