```open import Data.Sum
open import Data.Nat
open import Data.Unit
open import Data.Product
open import Relation.Binary.PropositionalEquality

-- plain (unindexed) trees
data Tree (α : Set) : Set where
Empty  : Tree α
Branch : Tree α → α → Tree α → Tree α

max : ℕ → ℕ → ℕ
max zero r = r
max r zero = r
max (suc l) (suc r) = suc (max l r)

depth : ∀ {α} → Tree α → ℕ
depth Empty = zero
depth (Branch t x t₁) = suc (max (depth t) (depth t₁))

-- depth-indexed trees
data DTree (α : Set) : ℕ → Set where
Empty : DTree α zero
Branch : ∀ {x y : ℕ} → DTree α x → α → DTree α y →
DTree α (suc (max x y))

-- convert an unindexed tree to an indexed tree
-- (unlike the GADT version we don't need existential wrapping)
dify : ∀{α} → (t : Tree α) → DTree α (depth t)
dify Empty = Empty
dify (Branch t x t₁) = Branch (dify t) x (dify t₁)

-- perfectly-balanced trees as a depth-indexed inductive type
data GTree (α : Set) : ℕ → Set where
Empty : GTree α zero
TreeG : ∀ {n} → GTree α n → α → GTree α n → GTree α (suc n)

-- perfectly-balanced trees defined recursively
gtree : Set → ℕ → Set
gtree α zero = ⊤
gtree α (suc n) = gtree α n × α × gtree α n

-- swivel on inductively-defined trees
Swivel : ∀ {α n} → GTree α n → GTree α n
Swivel Empty = Empty
Swivel (TreeG t x t₁) = TreeG (Swivel t₁) x (Swivel t)

-- swivel on recursively-defined trees, matching on the index (depth)
swivel : ∀ {α n} → gtree α n → gtree α n
swivel {α} {zero} t = tt
swivel {α} {suc n} (l , x , r) = swivel r , (x , swivel l)

-- swivel on unindexed trees
swivel' : ∀ {α} → Tree α → Tree α
swivel' Empty = Empty
swivel' (Branch t x t₁) = Branch (swivel' t₁) x (swivel' t)

{- external verification: unindexed definitions, separate proofs -}

-- max is commutative
max-comm  : ∀ {m n} → (max m n) ≡ (max n m)
max-comm {zero} {zero} = refl
max-comm {zero} {suc n} = refl
max-comm {suc m} {zero} = refl
max-comm {suc m} {suc n}  with max-comm {m} {n }
...                  |    foo = cong suc foo

-- max(m,n) is either m or n
max-either : ∀ {m n o} → (max m n ≡ o) → (o ≡ m) ⊎ (o ≡ n)
max-either {zero} {n} refl = inj₂ refl
max-either {suc m} {zero} refl = inj₁ refl
max-either {suc m} {suc n} refl with max-either {m} {n} refl
max-either {suc m} {suc n} refl | inj₁ x = inj₁ (cong suc x)
max-either {suc m} {suc n} refl | inj₂ y = inj₂ (cong suc y)

-- swivel on unindexed trees is depth-preserving
swiv-depth : ∀ {α} → (t : Tree α) → depth t ≡ depth (swivel' t)
swiv-depth Empty = refl
swiv-depth (Branch t x t₁)
with swiv-depth t | swiv-depth t₁
...  |     y          |      z =
let eq₁ = cong₂ max y z in
let eq₂ = trans eq₁ (max-comm {depth (swivel' t)} {depth (swivel' t₁)}) in
cong suc eq₂
```