ChurchNat

module Declarative.Examples.StdLib.ChurchNat where
open import Data.Integer using ()
open import Relation.Binary.PropositionalEquality using (refl)

open import Utils using (Kind;*)
open import Type using (Ctx⋆;_⊢⋆_;Z)
open _⊢⋆_
open import Declarative using (Ctx;_⊢_;_∋_)
open Ctx
open _⊢_
open _∋_
open import Type.RenamingSubstitution using (sub∅)
open import Builtin using (addInteger)
open import Builtin.Constant.Type using (TyCon;aInteger)
open import Type.Equality using (_≡β_)
open _≡β_
open TyCon
integer = atomic aInteger

-- all (r :: *). r -> (r -> r) -> r
N : ∀{Φ}  Φ ⊢⋆ *
N = Π (` Z  (` Z  ` Z)  ` Z)

-- /\(r :: *) -> \(z : r) (f : r -> r) -> z
Zero :   N
Zero = Λ (ƛ (ƛ (` (S Z))))

-- \(n : nat) -> /\(r :: *) -> \(z : r) (f : r -> r) -> f (n {r} z f)
Succ :   N  N
Succ = ƛ (Λ (ƛ (ƛ (` Z · ((` (S (S (T Z)))) ·⋆ (` Z) · (` (S Z)) · (` Z))))))

Iter : ∀{Φ}{Γ : Ctx Φ}  Γ  Π (` Z  (` Z  ` Z)  N  (` Z))
Iter = Λ (ƛ (ƛ (ƛ ((` Z) ·⋆ (` Z) · (` (S (S Z))) · (` (S Z))))))

con0 : ∀{Φ}{Γ : Ctx Φ}  Γ  con (^ integer)
con0 = con {A = ^ integer}(ℤ.pos 0) (refl≡β (^ (atomic aInteger)))

con1 : ∀{Φ}{Γ : Ctx Φ}  Γ  con (^ integer)
con1 = con {A = ^ integer}(ℤ.pos 1) (refl≡β (^ (atomic aInteger)))

inc : ∀{Φ}{Γ : Ctx Φ}  Γ  con (^ integer)  con (^ integer)
inc = ƛ (builtin addInteger · con1  · ` Z)

Nat2Int :   N  con (^ integer)
Nat2Int = ƛ (Iter
  ·⋆ con (^ integer)
  ·  con0
  ·  inc
  ·  ` Z)