通过(monadic)join和fmap进行终止检查替换

时间:2014-02-27 07:44:30

标签: monads substitution termination agda

我正在使用大小的类型,并且对于类型化术语具有替换函数,如果我直接给出定义,则终止检查,但如果我通过(monadic)join和fmap考虑它则不会。

{-# OPTIONS --sized-types #-}

module Subst where

   open import Size

要显示问题,就足以拥有单位和总和。我的数据类型为TrieTerm,我在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)
   θ *ᵀ 〔 κ₁ , κ₂ 〕 = 〔 θ *ᵀ κ₁ , θ *ᵀ κ₂ 〕

但是,TrieTerm是仿函数,所以很自然地希望根据<$>(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终止检查的相互递归版本,或者我是否明确地写了替换?

1 个答案:

答案 0 :(得分:1)

join以下类型:

join : ∀ {ι A Γ τ} → Term (Term A) {ι} Γ τ → Term A Γ τ

(来自gallais' comment以上)。