{-# OPTIONS --without-K --safe #-} module Induction.Nat.Strong where open import Data.Nat.Base open import Data.Nat.Properties open import Relation.Unary open import Function infix 9 □_ record □_ {l} (A : ℕ → Set l) (n : ℕ) : Set l where constructor mkBox field call : ∀ {m} → .(m < n) → A m open □_ public module _ {l} {A B : ℕ → Set l} where map : ∀[ A ⇒ B ] → ∀[ □ A ⇒ □ B ] call (map f A) m<n = f (call A m<n) module _ {l} {A : ℕ → Set l} where extract : ∀[ □ A ] → ∀[ A ] extract a = call a ≤-refl duplicate : ∀[ □ A ⇒ □ □ A ] call (call (duplicate A) m<n) p<m = call A (<-trans p<m m<n) ≤-lower : {m n : ℕ} → .(m ≤ n) → (□ A) n → (□ A) m call (≤-lower m≤n A) p<m = call A (≤-trans p<m m≤n) <-lower : {m n : ℕ} → .(m < n) → (□ A) n → (□ A) m call (<-lower m<n A) p<m = call A (<-trans p<m m<n) fix□ : ∀[ □ A ⇒ A ] → ∀[ □ A ] call (fix□ f {zero}) () call (fix□ f {suc n}) m<sn = f (≤-lower (≤-pred m<sn) (fix□ f)) module _ {l} {A B : ℕ → Set l} where map2 : {C : ℕ → Set l} → ∀[ A ⇒ B ⇒ C ] → ∀[ □ A ⇒ □ B ⇒ □ C ] call (map2 f A B) m<n = f (call A m<n) (call B m<n) app : ∀[ □ (A ⇒ B) ⇒ (□ A ⇒ □ B) ] call (app F A) m<n = call F m<n (call A m<n) fix : ∀ {l} (A : ℕ → Set l) → ∀[ □ A ⇒ A ] → ∀[ A ] fix A = extract ∘ fix□ module _ {l} {A : ℕ → Set l} where <-close : (∀ {m n} → .(m < n) → A n → A m) → ∀[ A ⇒ □ A ] call (<-close down a) m<n = down m<n a ≤-close : (∀ {m n} → .(m ≤ n) → A n → A m) → ∀[ A ⇒ □ A ] ≤-close down = <-close (λ .m<n → down (<⇒≤ m<n)) loeb : ∀[ □ (□ A ⇒ A) ⇒ □ A ] loeb = fix (□ (□ A ⇒ A) ⇒ □ A) $ λ rec f → mkBox λ m<n → call f m<n (call rec m<n (call (duplicate f) m<n))