在应用程序中使用subst会搞砸结果的类型

时间:2015-12-01 04:31:25

标签: agda

我有以下类型的定义:

insert : ∀ {n} → (i : Fin (suc n)) → ∀ t → Env n → Env (suc n)
weaken : ∀ {t t₀ n} {Γ : Env n} → (i : Fin (suc n)) → (e : Γ ⊢ t₀) → (insert i t Γ) ⊢ t₀

鉴于两个环境Γ : Env nΓ′ : Env n′,以及指向第二个i : Fin (suc n)中某个位置的指针,我想削弱e : (Γ′ ++ Γ) ⊢ t₀ 1}}。

理论上,使用类似

之类的东西应该很容易
let i′ = raise n′ i
weaken {t} i′ e : insert i′ t (Γ′ ++ Γ) ⊢ t₀

然而,在实践中它并没有那么好用,因为类型检查员不相信raise n′ i具有Fin (suc _)类型(weaken所需):

  类型为(n′ + suc n)

(suc (_n_550 i e))!=   当检查时   表达式i′的类型为Fin (suc (_n_550 i e))

我的问题是,我可以使用+-suc : ∀ n′ n → n′ + suc n ≡ suc (n′ + n)之类的内容subst来确定i′的类型,但weaken i′ e生成的类型不会有insert i′ t (Γ′ ++ Γ) ⊢ t₀的格式{ {1}}。

1 个答案:

答案 0 :(得分:2)

  

给定两个环境Γ : Env nΓ′ : Env n′

这些都是背景。

应该可以将insert的类型更改为

data Bound : ℕ -> Set where
  zero : ∀ {n} -> Bound n
  suc  : ∀ {n} -> Bound n -> Bound (suc n)

insert : ∀ {n} → (i : Bound n) → ∀ t → Env n → Env (suc n)

不改变功能的主体。

您可以在raise下编写suc版本:

raise′ : ∀ {m} n → Fin (suc m) → Fin (suc (n + m))
raise′ zero    i = i
raise′ (suc n) i = suc (raise′ n i)

但实际的解决方案是使用任一函数重命名术语:

Ren : Con -> Con -> Set
Ren Γ Δ = ∀ {σ} -> σ ∈ Γ -> σ ∈ Δ

keepʳ : ∀ {Γ Δ σ} -> Ren Γ Δ -> Ren (Γ ▻ σ) (Δ ▻ σ)
keepʳ r  vz    = vz
keepʳ r (vs v) = vs (r v)

ren : ∀ {Γ Δ σ} -> Ren Γ Δ -> Γ ⊢ σ -> Δ ⊢ σ
ren r (var v) = var (r v)
ren r (ƛ b  ) = ƛ (ren (keepʳ r) b)
ren r (f · x) = ren r f · ren r x

order preserving embeddings