\begin{code}
module TermAcc where

open import Atom
open import Term

-- Induction over terms size, perserved under swapping
open import Data.Nat
open import NaturalProperties
open import Induction.WellFounded
open import Induction.Nat
open import Relation.Binary.PropositionalEquality
--
data ΛAcc : Λ  Set where
  accv   : {a : Atom}   ΛAcc (v a)
  acc·   : {M N : Λ}    ΛAcc M  ΛAcc N  ΛAcc (M · N)
  accƛ   : {a : Atom}{M : Λ}  ((b : Atom)  ΛAcc ( a  b  M))  ΛAcc (ƛ a M)
--
accTerms :  M m  Acc _<′_ m   M   m  ΛAcc M
accTerms (v x)   .1              _      refl  = accv
accTerms (M · N) .( M  +  N )  (acc f) refl  
  = acc·  (accTerms M  M  (f  M  ((lemman>0→m+1≤m+n { M } { N } (lemma∣M∣>0 {N})))) refl) 
          (accTerms N  N  (f  N  ((lemmam>0→n+1≤m+n { M } { N } (lemma∣M∣>0 {M})))) refl)
accTerms (ƛ a M) .(1 +  M )     (acc f) refl  
  = accƛ  b  accTerms ( a  b  M)  M  (f  M  ≤′-refl)  (lemma∙∣∣ {M}))
--
accesibleTerms :  M  ΛAcc M
accesibleTerms M = accTerms M  M  (<-well-founded  M ) refl
--
data ΛAccSizeƛ : Λ  Set where
  accSv   : {a : Atom}   ΛAccSizeƛ (v a)
  accS·   : {M N : Λ}    ΛAccSizeƛ M  ΛAccSizeƛ N  ΛAccSizeƛ (M · N)
  accSƛ   : {a : Atom}{M : Λ}  ((N : Λ)   N  <′ 1 +  M   ΛAccSizeƛ N)  ΛAccSizeƛ (ƛ a M)
--
accTermSizes :  M m  Acc _<′_ m   M   m  ΛAccSizeƛ M
accTermSizes (v x)   .1              _      refl  = accSv
accTermSizes (M · N) .( M  +  N )  (acc f) refl  
  = accS·  (accTermSizes M  M  (f  M  ((lemman>0→m+1≤m+n { M } { N } (lemma∣M∣>0 {N})))) refl) 
           (accTermSizes N  N  (f  N  ((lemmam>0→n+1≤m+n { M } { N } (lemma∣M∣>0 {M})))) refl)
accTermSizes (ƛ a M) .(1 +  M )     (acc f) refl  
  = accSƛ   N ∣N∣<1+∣M∣  accTermSizes N  N  (f  N  ∣N∣<1+∣M∣)  refl)
--
getFirstacc· : {M N : Λ}  ΛAccSizeƛ (M · N)  ΛAccSizeƛ M
getFirstacc· (accS· accM accN) = accM
--
getSecondacc· : {M N : Λ}  ΛAccSizeƛ (M · N)  ΛAccSizeƛ N
getSecondacc· (accS· accM accN) = accN
--
accesibleTermsSizesƛ :  M  ΛAccSizeƛ M
accesibleTermsSizesƛ M = accTermSizes M  M  (<-well-founded  M ) refl
\end{code}