抽象了呼叫站点后,终止检查器将失败

时间:2019-04-02 04:47:15

标签: agda coinduction

问题

我有一个简单的归纳记录,其中一个字段是求和类型。 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

尝试的解决方案

  1. 使用Agda version 2.5.4.2。无法解决。
  2. 使用--termination-depth=10。无法解决。

2 个答案:

答案 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₂作为表达式的顶层。