我正在使用大小的类型,并且对于类型化术语具有替换函数,如果我直接给出定义,则终止检查,但如果我通过(monadic)join和fmap考虑它则不会。
{-# OPTIONS --sized-types #-}
module Subst where
open import Size
要显示问题,就足以拥有单位和总和。我的数据类型为Trie
和Term
,我在Term
内使用Term
的密码域进行尝试,作为和的消除形式的一部分。
data Type : Set where
: Type
_+_ : Type → Type → Type
postulate Cxt : Set → Set
-- Every value in the trie is typed in a context obtained by extending Γ.
data Trie (A : Cxt Type → Set) : {ι : Size} → Type → Cxt Type → Set where
〈〉 : ∀ {ι Γ} → A Γ → Trie A {↑ ι} Γ
〔_,_〕 : ∀ {ι τ₁ τ₂ Γ} →
Trie A {ι} τ₁ Γ → Trie A {ι} τ₂ Γ → Trie A {↑ ι} (τ₁ + τ₂) Γ
-- The elimination form for + types is a trie whose values are terms.
data Term (A : Cxt Type → Type → Set) : {ι : Size} →
Cxt Type → Type → Set where
var : ∀ {ι Γ τ} → A Γ τ → Term A {↑ ι} Γ τ
inl : ∀ {ι Γ τ₁ τ₂} → Term A {ι} Γ τ₁ → Term A {↑ ι} Γ (τ₁ + τ₂)
match_as_ : ∀ {ι Γ τ τ′} → Term A {ι} Γ τ →
Trie (λ Γ → Term A {ι} Γ τ′) {ι} τ Γ → Term A {↑ ι} Γ τ′
现在,如果我直接将替换定义为术语(与使用codomain Term
的替换相互替换),则定义终止检查,即使没有大小索引。
-- Define substitution directly.
_*_ : ∀ {A Γ Γ′ τ} → (∀ {τ} → A Γ τ → Term A Γ′ τ) → Term A Γ τ → Term A Γ′ τ
_*ᵀ_ : ∀ {A Γ Γ′ τ τ′} → (∀ {τ} → A Γ τ → Term A Γ′ τ) →
Trie (λ Γ → Term A Γ τ) τ′ Γ → Trie (λ Γ → Term A Γ τ) τ′ Γ′
θ * var x = θ x
θ * inl e = inl (θ * e)
θ * (match e as κ) = match (θ * e) as (θ *ᵀ κ)
θ *ᵀ 〈〉 x = 〈〉 (θ * x)
θ *ᵀ 〔 κ₁ , κ₂ 〕 = 〔 θ *ᵀ κ₁ , θ *ᵀ κ₂ 〕
但是,Trie
和Term
是仿函数,所以很自然地希望根据<$>
(fmap)和join
来定义替换,其中后者会折叠术语的术语。请注意<$>
及其对应的尝试是保持大小的,实际上我们需要使用反映这一点的大小索引来满足它终止的Agda。
-- Size-preserving fmap.
_<$>ᵀ_ : ∀ {ι τ Γ Γ′} {A B : Cxt Type → Set } →
(A Γ → B Γ′) → Trie A {ι} τ Γ → Trie B {ι} τ Γ′
f <$>ᵀ (〈〉 x) = 〈〉 (f x)
f <$>ᵀ 〔 σ₁ , σ₂ 〕 = 〔 f <$>ᵀ σ₁ , f <$>ᵀ σ₂ 〕
_<$>_ : ∀ {ι A B Γ Γ′ τ} →
(∀ {τ} → A Γ τ → B Γ′ τ) → Term A {ι} Γ τ → Term B {ι} Γ′ τ
f <$> var x = var (f x)
f <$> inl e = inl (f <$> e)
f <$> match e as κ = match f <$> e as ((λ e → f <$> e) <$>ᵀ κ)
-- Monadic multiplication.
join : ∀ {A Γ τ} → Term (Term A) Γ τ → Term A Γ τ
join (var e) = e
join (inl e) = inl (join e)
join (match e as κ) = match join e as (join <$>ᵀ κ)
-- Now substitution is easily defined in terms of join and fmap.
_*′_ : ∀ {A Γ Γ′ τ} → (∀ {τ} → A Γ τ → Term A Γ′ τ) → Term A Γ τ → Term A Γ′ τ
θ *′ e = join (θ <$> e)
不幸的是join
没有终止检查,我不确定是否可以使用大小索引来说服Agda这样做。直观地,很明显,如果你有一棵树的最大深度为1,并且你用最大深度为1的树替换它的叶子,你会得到一棵树的最大深度为(1 + 1)。但我不认为这是你可以用尺寸类型建立的那种东西,或者如果可以的话它是否会有所帮助。请注意,如果没有通过join <$>ᵀ
进行相互递归尝试,则函数终止 - 检查正常。
有没有办法让这个join
终止检查的相互递归版本,或者我是否明确地写了替换?
答案 0 :(得分:1)