【发布时间】:2014-02-26 01:26:14
【问题描述】:
我很难说服 Agda 终止 - 检查下面的函数 fmap 以及在 Trie 的结构上递归定义的类似函数。 Trie 是 trie,其域是 Type,它是由单元、乘积和不动点组成的对象级类型(我省略了联积以保持代码最小化)。这个问题似乎与我在Trie 的定义中使用的类型级替换有关。 (表达式const (μₜ τ) * τ 表示将替换const (μₜ τ) 应用于类型τ。)
module Temp where
open import Data.Unit
open import Category.Functor
open import Function
open import Level
open import Relation.Binary
-- A context is just a snoc-list.
data Cxt {????} (A : Set ????) : Set ???? where
ε : Cxt A
_∷ᵣ_ : Cxt A → A → Cxt A
-- Context membership.
data _∈_ {????} {A : Set ????} (a : A) : Cxt A → Set ???? where
here : ∀ {Δ} → a ∈ Δ ∷ᵣ a
there : ∀ {Δ a′} → a ∈ Δ → a ∈ Δ ∷ᵣ a′
infix 3 _∈_
-- Well-formed types, using de Bruijn indices.
data _⊦ (Δ : Cxt ⊤) : Set where
nat : Δ ⊦
???? : Δ ⊦
var : _ ∈ Δ → Δ ⊦
_+_ _⨰_ : Δ ⊦ → Δ ⊦ → Δ ⊦
μ : Δ ∷ᵣ _ ⊦ → Δ ⊦
infix 3 _⊦
-- A closed type.
Type : Set
Type = ε ⊦
-- Type-level substitutions and renamings.
Sub Ren : Rel (Cxt ⊤) zero
Sub Δ Δ′ = _ ∈ Δ → Δ′ ⊦
Ren Δ Δ′ = ∀ {x} → x ∈ Δ → x ∈ Δ′
-- Renaming extension.
extendᵣ : ∀ {Δ Δ′} → Ren Δ Δ′ → Ren (Δ ∷ᵣ _) (Δ′ ∷ᵣ _)
extendᵣ ρ here = here
extendᵣ ρ (there x) = there (ρ x)
-- Lift a type renaming to a type.
_*ᵣ_ : ∀ {Δ Δ′} → Ren Δ Δ′ → Δ ⊦ → Δ′ ⊦
_ *ᵣ nat = nat
_ *ᵣ ???? = ????
ρ *ᵣ (var x) = var (ρ x)
ρ *ᵣ (τ₁ + τ₂) = (ρ *ᵣ τ₁) + (ρ *ᵣ τ₂)
ρ *ᵣ (τ₁ ⨰ τ₂) = (ρ *ᵣ τ₁) ⨰ (ρ *ᵣ τ₂)
ρ *ᵣ (μ τ) = μ (extendᵣ ρ *ᵣ τ)
-- Substitution extension.
extend : ∀ {Δ Δ′} → Sub Δ Δ′ → Sub (Δ ∷ᵣ _) (Δ′ ∷ᵣ _)
extend θ here = var here
extend θ (there x) = there *ᵣ (θ x)
-- Lift a type substitution to a type.
_*_ : ∀ {Δ Δ′} → Sub Δ Δ′ → Δ ⊦ → Δ′ ⊦
θ * nat = nat
θ * ???? = ????
θ * var x = θ x
θ * (τ₁ + τ₂) = (θ * τ₁) + (θ * τ₂)
θ * (τ₁ ⨰ τ₂) = (θ * τ₁) ⨰ (θ * τ₂)
θ * μ τ = μ (extend θ * τ)
data Trie {????} (A : Set ????) : Type → Set ???? where
〈〉 : A → ???? ▷ A
〔_,_〕 : ∀ {τ₁ τ₂} → τ₁ ▷ A → τ₂ ▷ A → τ₁ + τ₂ ▷ A
↑_ : ∀ {τ₁ τ₂} → τ₁ ▷ τ₂ ▷ A → τ₁ ⨰ τ₂ ▷ A
roll : ∀ {τ} → (const (μ τ) * τ) ▷ A → μ τ ▷ A
infixr 5 Trie
syntax Trie A τ = τ ▷ A
{-# NO_TERMINATION_CHECK #-}
fmap : ∀ {a} {A B : Set a} {τ} → (A → B) → τ ▷ A → τ ▷ B
fmap f (〈〉 x) = 〈〉 (f x)
fmap f 〔 σ₁ , σ₂ 〕 = 〔 fmap f σ₁ , fmap f σ₂ 〕
fmap f (↑ σ) = ↑ (fmap (fmap f) σ)
fmap f (roll σ) = roll (fmap f σ)
似乎fmap 在每种情况下都递归成一个严格更小的参数;如果我删除递归类型,产品案例当然很好。另一方面,如果我删除产品,该定义可以很好地处理递归类型。
这里最简单的方法是什么? inline/fuse trick 看起来并不特别适用,但也许确实适用。还是我应该寻找另一种方法来处理 Trie 定义中的替换?
【问题讨论】:
-
看起来你的一些 unicode 丢失了 :(
-
啊。不是在我安装的 Ubuntu 上;) 告诉我哪里有你看不到的字符,我会尝试发布一个更友好的版本。 (我想知道是不是特殊字体字符,比如?????)
-
我的意思是“字母符号”,而不是“字体字符”。
-
内联技巧实际上是适用的——只是看起来有点奇怪。可能有更好的方法,但如果您对此解决方案感到满意,我会将其作为答案发布。是的,unicode 似乎造成了一些麻烦(不适用于我的 Agda 模式,因为 DejaVu Sans + Code2000 几乎可以处理任何事情;另一方面,Gist ......)。 gist.github.com/vituscze/8773710
-
下标
t和s没有为我显示(我得到带有十六进制代码点的框)。看起来 stackoverflow 的 CSS 对代码块有更多的字体选择。
标签: recursion trie termination agda