{-# OPTIONS --safe --without-K #-}

module Examples.WithoutMacros.Nat where

open import Prelude

--open import Generics.Description
--open import Generics.Recursion
--open import Generics.Reflection
--
--open import Generics.RecursionScheme

--------
-- Connecting with the existing ℕ datatype

--instance
--  NatC : Named (quote ℕ) _
--  unNamed NatC = genDataC NatD (genDataT NatD ℕ)
--    where NatD = genDataD ℕ

--------
-- Fold operator and fusion theorem

--private
--  foldℕP : FoldP
--  foldℕP = fold-operator (quote ℕ)

foldℕ : { : Level} {X : Set } (alg : X) (alg1 : (z : X)  X)
        (z : ) 
        X
foldℕ { = } {X = X} alg alg₁ zero = alg
foldℕ { = } {X = X} alg alg₁ (suc n) = alg₁ (foldℕ {} {X} alg alg₁ n)

--instance foldℕC = genFoldC foldℕP foldℕ

--private
--  foldℕ-fusionP : IndP
--  foldℕ-fusionP = fold-fusion (quote ℕ)

foldℕ-fusion : { ℓ1 : Level} {X : Set } {Y : Set ℓ1}
               (h : (z : X)  Y) {f : X} {f1 : (z : X)  X} {g : Y}
               {g1 : (z : Y)  Y} (hom : _≡_ {ℓ1} {Y} (h f) g)
               (hom1
                : (xs : X) (ys : Y) (z : _≡_ {ℓ1} {Y} (h xs) ys) 
                  _≡_ {ℓ1} {Y} (h (f1 xs)) (g1 ys))
               (n : ) 
               _≡_ {ℓ1} {Y} (h (foldℕ {} {X} f f1 n)) (foldℕ {ℓ1} {Y} g g1 n)
foldℕ-fusion { = } {ℓ1 = ℓ₁} {X = X} {Y = Y} h {f = f} {f1 = f₁} {g = g} {g1 = g₁} hom hom₁ zero = hom
foldℕ-fusion { = } {ℓ1 = ℓ₁} {X = X} {Y = Y} h {f = f} {f1 = f₁} {g = g} {g1 = g₁} hom hom₁ (suc n) = hom₁ (foldℕ {} {X} f f₁ n) (foldℕ {ℓ₁} {Y} g g₁ n) (foldℕ-fusion {} {ℓ₁} {X} {Y} h {f} {f₁} {g} {g₁} hom hom₁ n)

--instance foldℕ-fusionC = genIndC foldℕ-fusionP foldℕ-fusion

--------
-- Induction operator

--private
--  indℕP : IndP
--  indℕP = ind-operator (quote ℕ)

indℕ : { : Level} (P : (z : )  Set ) (ind-case : P 0)
       (ind-case1 : (ns : ) (z : P ns)  P (suc ns)) (n : ) 
       P n
indℕ { = } P ind-case ind-case₁ zero = ind-case
indℕ { = } P ind-case ind-case₁ (suc n) = ind-case₁ n
                                            (indℕ {} P ind-case ind-case₁ n)

--instance indℕC = genIndC indℕP indℕ