3
votes

I want to define a size-preserving function on derivations of a transition relation for pi calculus. I'm not able to convince Agda that it is indeed size-preserving. I'm also getting an error message which appears non-sensical, so perhaps there's a clue in there.

I've boiled the code down as much as possible whilst still retaining the flavour of the setting. Here's the preamble.

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

module SizedTypes where

   open import Data.Product public hiding (swap)
   open import Relation.Binary.PropositionalEquality
   open import Size

   -- Processes.
   data Proc : Set where
      ν_ : Proc → Proc

   -- Actions.
   data ⟿ᵇ : Set where
      input : ⟿ᵇ
      boundOut : ⟿ᵇ

   data ⟿ᶜ : Set where
      out : ⟿ᶜ

   data ⟿ : Set where
      _ᵇ : ⟿ᵇ → ⟿
      _ᶜ : ⟿ᶜ → ⟿

   -- Renamings.
   data Ren : Set where

   postulate
      push : Ren
      swap : Ren
      _ᴬ*_ : Ren → ⟿ᶜ →  ⟿ᶜ

   -- Transitions.
   data _—[_]→_ : {ι : Size} → Proc → (a : ⟿) → Proc → Set where
      ν•_ : ∀ {ι P R} → _—[_]→_ {ι = ι} P (out ᶜ) R →
            _—[_]→_ {ι = ↑ ι} (ν P) (boundOut ᵇ) R
      νᵇ_ : ∀ {ι P R} {a : ⟿ᵇ} → _—[_]→_ {ι = ι} P (boundOut ᵇ) R →
            _—[_]→_ {ι = ↑ ι} (ν P) (a ᵇ) (ν R)
      νᶜ_ : ∀ {ι P R} → _—[_]→_ {ι = ι} P ((push ᴬ* out) ᶜ) R →
            _—[_]→_ {ι = ↑ ι} (ν P) (out ᶜ) (ν R)

   infixl 0 _—[_]→_

   postulate
      _ᴾ*_ : Ren → Proc → Proc
      _ᵀ*_ : ∀ {ι} (ρ : Ren) {P R} {a : ⟿ᶜ} → _—[_]→_ {ι = ι} P (a ᶜ) R →
             _—[_]→_ {ι = ι} (ρ ᴾ* P) ((ρ ᴬ* a) ᶜ) (ρ ᴾ* R)
      swap-involutive : ∀ (P : Proc) → swap ᴾ* swap ᴾ* P ≡ P
      swap∘push : swap ᴬ* push ᴬ* out ≡ out

   infixr 8 _ᵀ*_ _ᴾ*_ _ᴬ*_

   -- Structural congruence.
   infix 4 _≅_
   data _≅_ : Proc → Proc → Set where
      νν-swap : ∀ P → ν (ν (swap ᴾ* P)) ≅ ν (ν P)

Now here's what I can't make work.

   -- "Residual" of a transition E after a structural congruence φ.
   ⊖ : ∀ {ι P P′} {a : ⟿} {R} (E : _—[_]→_ {ι = ι} P a R) (φ : P ≅ P′) →
       Σ[ R ∈ Proc ] _—[_]→_ {ι = ι} P′ a R
   ⊖ (ν•_ (νᶜ E)) (νν-swap P) with swap ᵀ* E
   ... | swap*E rewrite swap-involutive P | swap∘push =
      _ , {!!} -- νᵇ (ν• swap*E)
   ⊖ E φ = {!!}

Roughly, I'm matching on the situation where there are adjacent ν binders, and showing that if I transpose the binders (by applying the 'swap' renaming under the binders) then the associated steps in the derivation also tranpose. Intuitively this preserves the size of the transition derivation.

Toggling hidden arguments (in Emacs) reveals that the goal in the problematic clause has type _—[_]→_ {↑ (↑ .ι)}, so I expect to be able to apply two constructors (in this case νᵇ and ν•). I can also see that E has type _—[_]→_ {.ι}, as does swap*E, and so I (naively) expect νᵇ (ν• swap*E) to be size-consistent with the goal. However Agda complains that the constraints are inconsistent.

Weirdly, if I use a with clause to introduce ν• swap*E into the context, then I get the following error:

.ι !=< P of type Size
when checking that the expression E has type
swap ᴾ* P —[ (push ᴬ* out) ᶜ ]→ .R

This is baffling because the choice of meta-variable P suggests that Agda is trying to match a size index against a variable of type Proc.

What am I doing wrong here?

2

2 Answers

3
votes

Thanks to Andrea Vezzosi for answering this on the Agda mailing list. In this instance it's as simple as passing the ι index explicitly:

⊖ (ν• (νᶜ_ {ι} E)) (νν-swap P) with swap ᵀ* E
   ... | swap*E rewrite swap-involutive P | swap∘push
     = _ , νᵇ (ν•_ {ι = ι} swap*E)
1
votes

Turns out this was a bug which was fixed in Agda 2.4.0.2. One can now simply write:

⊖ (ν• (νᶜ E)) (νν-swap P) with swap ᵀ* E
   ... | swap*E rewrite swap-involutive P | swap∘push
     = _ , νᵇ (ν• swap*E)

as one would expect.