[Agda] Eta reduction of a function argument in a where block

Wojciech Jedynak wjedynak at gmail.com
Sun Aug 7 19:38:21 CEST 2011


Hello everybody!

I have been playing with Martin-Loef's W-types and I noticed a strange
Agda behavior while using the recursor for W-flavored naturals.
I think that in one of the cases in the code below, a function defined
in a where block receives an additional parameter when it's not
supposed to.

I'm sorry that the code is a big long.
The gist is that the function toℕ defined in modules Inside behaves
differently from the one from the InsideEta and Outside modules.

Greetings,
Wojciech Jedynak

\begin{code}

module WTypes where

open import Data.Nat
open import Data.Empty
open import Data.Unit
open import Function
open import Relation.Binary.PropositionalEquality

-- We define W-types and a recursor on them.

data W : (A : Set) → (B : A → Set) → Set₁ where
  sup : {A : Set} {B : A → Set}
      → (a : A) → (B a → W A B) → W A B

wrec : {A : Set}
     → {B : A → Set}
     → (C : W A B → Set)
     → (d : (x : A)
          → (y : B x → W A B)
          → ((z : B x) → C (y z))
          → C (sup x y))
     → (w : W A B)
     → C w
wrec C d (sup a b) = d a b (λ z → wrec C d (b z))

-----------------------
--  Natural numbers  --
-----------------------

data nat-cs : Set where
  Z S : nat-cs

nat-record : nat-cs → Set
nat-record Z = ⊥
nat-record S = ⊤

nat : Set₁
nat = W nat-cs nat-record

n-zero : nat
n-zero = sup Z ⊥-elim

n-suc : nat → nat
n-suc n = sup S (λ top → n)

\end{code}

To see if the above definition is "correct" we want to
write convertions between ℕ and nat types, and prove them correct.

Whether we can actually do the proof seems to depend on
some cosmetic changes!

Suppose we write:

\begin{code}

fromℕ : ℕ → nat
fromℕ zero    = n-zero
fromℕ (suc n) = n-suc (fromℕ n)

-- with iter in a where block

module Inside where

  toℕ : nat → ℕ
  toℕ n = wrec _ iter n module TN where
    iter : (x : nat-cs)
         → (nat-record x → nat)
         → (nat-record x → ℕ)
         → ℕ
    iter Z _ rec = 0
    iter S _ rec = 1 + rec tt

module InsideEta where

  toℕ : nat → ℕ
  toℕ = wrec _ iter module TN where
    iter : (x : nat-cs)
         → (nat-record x → nat)
         → (nat-record x → ℕ)
         → ℕ
    iter Z _ rec = 0
    iter S _ rec = 1 + rec tt

module Outside where
  iter : (x : nat-cs)
       → (nat-record x → nat)
       → (nat-record x → ℕ)
       → ℕ
  iter Z _ rec = 0
  iter S _ rec = 1 + rec tt

  toℕ : nat → ℕ
  toℕ n = wrec _ iter n

\end{code}

We want to prove that toℕ (fromℕ n) ≡ n, for all n : ℕ,
but it seems possible only in the second and third case!

\begin{code}

lem : ∀ (n : ℕ) → Inside.toℕ (fromℕ n) ≡ n
lem zero = refl
lem (suc n) with lem n
... | rec = {!!} --cong suc rec

lem2 : ∀ (n : ℕ) → InsideEta.toℕ (fromℕ n) ≡ n
lem2 zero = refl
lem2 (suc n) with lem2 n
... | rec = cong suc rec

lem3 : ∀ (n : ℕ) → Outside.toℕ (fromℕ n) ≡ n
lem3 zero = refl
lem3 (suc n) with lem3 n
... | rec = cong suc rec

\end{code}

When we write 'cong suc rec' in the goal in lem, we get an error:

  fromℕ n != sup S (λ top → fromℕ n) of type W nat-cs nat-record
  when checking that the expression cong suc rec has type
  suc (wrec (λ n → ℕ) (TN.iter (sup S (λ top → fromℕ n))) (fromℕ n)) ≡ suc n

the context in the goal is:

  Goal: suc (wrec (λ n' → ℕ) (TN.iter (sup S (λ top → fromℕ n))) (fromℕ n))
      ≡ suc n
  ————————————————————————————————————————————————————————————
  rec : wrec (λ n' → ℕ) (TN.iter (fromℕ n)) (fromℕ n) ≡ n
  n   : ℕ

The strange thing is that Agda thinks that TN.iter from Inside depends on
the nat argument of toℕ.

Everything works in lem2 and lem3. The context is

  Goal: suc (wrec (λ w → ℕ) TN.iter (fromℕ n)) ≡ suc n
  ————————————————————————————————————————————————————————————
  rec : wrec (λ w → ℕ) TN.iter (fromℕ n) ≡ n

EOF


More information about the Agda mailing list