Skip to content

Instantly share code, notes, and snippets.

@Trebor-Huang
Last active September 24, 2022 14:48
Show Gist options
  • Save Trebor-Huang/46a61cbd2427ea51901be7215a5280e5 to your computer and use it in GitHub Desktop.
Save Trebor-Huang/46a61cbd2427ea51901be7215a5280e5 to your computer and use it in GitHub Desktop.
General Recursive Functions in Agda
module _ where
open import Data.Nat using (β„•; suc; _+_)
open import Data.Fin using (Fin) renaming (zero to 𝕫; suc to 𝕀_)
open import Data.Vec using (Vec; []; [_]; _∷_; tail; map; allFin) renaming (lookup to _!_)
open import Data.Vec.Relation.Binary.Pointwise.Inductive using (Pointwise; []; _∷_)
open import Data.Vec.Relation.Binary.Equality.Propositional using (_≋_; ≋⇒≑)
open import Relation.Binary.PropositionalEquality using (_≑_; refl; cong)
variable
n m n' : β„•
i j : Fin n
data Rec : β„• β†’ Set where
Z : Rec 0
S : Rec 1
Ο€_ : Fin n β†’ Rec n
_∘_ : Rec n β†’ Vec (Rec m) n β†’ Rec m
-- 2 more arguments: (x-1) and f(x-1, xs)
ρ : Rec n β†’ Rec (2 + n) β†’ Rec (1 + n)
ΞΌ : Rec (1 + n) β†’ Rec n
Id : Vec (Rec n) n
Id = map Ο€_ (allFin _)
Add : Rec 2
Add = ρ (Ο€ 𝕫) (S ∘ [ Ο€ 𝕀 𝕫 ])
infix 3 [_]_≫_ -- Big step
data [_]_≫_ : Rec n β†’ Vec β„• n β†’ β„• β†’ Set where
Z : [ Z ] [] ≫ 0
S : [ S ] [ n ] ≫ 1 + n
Ο€_ : βˆ€ i {v : Vec β„• n} β†’ [ Ο€ i ] v ≫ v ! i
_∘_ : {f : Rec n} {gs : Vec (Rec m) n}
β†’ {ms : Vec β„• m} {ns : Vec β„• n} {r : β„•}
β†’ [ f ] ns ≫ r
β†’ Pointwise ([_] ms ≫_) gs ns
β†’ [ f ∘ gs ] ms ≫ r
ρZ : {base : Rec n} {rec : Rec (2 + n)}
β†’ {ns : Vec β„• n} {m : β„•}
β†’ [ base ] ns ≫ m
β†’ [ ρ base rec ] 0 ∷ ns ≫ m
ρS : {base : Rec n} {rec : Rec (2 + n)}
β†’ {ns : Vec β„• n} {n m r : β„•} -- note that n is shadowed
β†’ [ ρ base rec ] n ∷ ns ≫ m
β†’ [ rec ] n ∷ m ∷ ns ≫ r
β†’ [ ρ base rec ] 1 + n ∷ ns ≫ r
ΞΌZ : {f : Rec (1 + n)} {ns : Vec β„• n}
β†’ [ f ] 0 ∷ ns ≫ 0
β†’ [ ΞΌ f ] ns ≫ 0
ΞΌS : {f : Rec (1 + n)} {ns : Vec β„• n} {m r : β„•}
β†’ [ f ] 0 ∷ ns ≫ 1 + m
β†’ [ ΞΌ (f ∘ (S ∘ [ Ο€ 𝕫 ] ∷ tail Id)) ] ns ≫ r
β†’ [ ΞΌ f ] ns ≫ 1 + r
module General where
{-# TERMINATING #-}
minimize : (β„• β†’ β„•) β†’ β„•
minimize f with f 0
... | 0 = 0
... | suc n = suc (minimize Ξ» n β†’ f (suc n))
{-# TERMINATING #-}
exec : Rec n β†’ Vec β„• n β†’ β„•
exec Z ns = 0
exec S (n ∷ []) = 1 + n
exec (Ο€ i) ns = ns ! i
exec (f ∘ gs) ns = exec f (map (Ξ» g β†’ exec g ns) gs)
exec (ρ f g) (0 ∷ ns) = exec f ns
exec (ρ f g) (suc n ∷ ns) = exec g (n ∷ exec (ρ f g) (n ∷ ns) ∷ ns)
exec (ΞΌ f) ns = minimize Ξ» n β†’ exec f (n ∷ ns)
test : β„• -- 11
test = exec Add (5 ∷ 6 ∷ [])
-- uniqueness of the results
unique : {f : Rec n} {ns : Vec β„• n} {m n : β„•}
β†’ [ f ] ns ≫ m
β†’ [ f ] ns ≫ n
β†’ m ≑ n
PointwiseUnique : {fs : Vec (Rec n) m} {rs : Vec β„• n} {ms ns : Vec β„• m}
β†’ Pointwise ([_] rs ≫_) fs ms
β†’ Pointwise ([_] rs ≫_) fs ns
β†’ ms ≑ ns
unique Z Z = refl
unique S S = refl
unique (Ο€ i) (Ο€ .i) = refl
unique (p ∘ ps) (q ∘ qs) rewrite PointwiseUnique ps qs = unique p q
unique (ρZ p) (ρZ q) = unique p q
unique (ρS p r) (ρS q s) rewrite unique p q = unique r s
unique (ΞΌZ p) (ΞΌZ q) = refl
unique (ΞΌZ p) (ΞΌS q _) with unique p q
... | ()
unique (ΞΌS p _) (ΞΌZ q) with unique p q
... | ()
unique (ΞΌS p r) (ΞΌS q s) = cong suc (unique r s)
PointwiseUnique [] [] = refl
PointwiseUnique (p ∷ ps) (q ∷ qs)
rewrite unique p q | PointwiseUnique ps qs = refl
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment