【问题标题】:Termination checker fails after abstracting the call site抽象呼叫站点后终止检查器失败
【发布时间】:2019-04-02 04:47:15
【问题描述】:

问题

我有一个简单的共归纳记录,其中包含一个 sum 类型的字段。 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。无法修复。

【问题讨论】:

    标签: agda coinduction


    【解决方案1】:

    你可以在这里使用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
    

    更明确地说明invalid₀ 定义中的Size 参数:

    step (invalid₀ {i} x) {j} = maybe (λ _ → inj₂ (invalid₀ {j} x)) (inj₁ unit) x
    

    其中j 的类型为Size&lt; i,因此对invalid₀ 的递归调用是在“较小的”Size 上。

    请注意,valid 不需要任何“帮助”即可通过终止检查,根本不需要推理 Size

    【讨论】:

      【解决方案2】:

      问题是 Agda 看不到 invalid₀ 是有效的。这是因为它既是递归的,又不受构造函数的保护。在决定这是否终止时,Agda 不会查看 maybe 的定义。

      这是一个满足终止检查器的实现,因为两个分支都由构造函数和/或非递归保护:

      okay₀ : Maybe Unit → Stream
      step (okay₀ x@(just _)) = inj₂ (invalid₀ x)
      step (okay₀ nothing) = inj₁ unit
      

      重要的部分是递归just case 有构造函数inj₂ 作为表达式的顶层。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多