Skip to content

Instantly share code, notes, and snippets.

@gelisam
Created April 16, 2024 04:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gelisam/b9d27de7fe757d64980da7be0e40c2a7 to your computer and use it in GitHub Desktop.
Save gelisam/b9d27de7fe757d64980da7be0e40c2a7 to your computer and use it in GitHub Desktop.
cata for N mutually-recursive types
open import Data.List using (List; _∷_; [])
open import Data.Maybe
open import Data.Nat
open import Data.Nat.Show renaming (show to showℕ)
open import Data.String
open import Relation.Binary.PropositionalEquality
{-# NO_POSITIVITY_CHECK #-}
data FixI {Index : Set} (f : (Index → Set) → (Index → Set)) (i : Index) : Set where
InI
: f (FixI f) i
→ FixI f i
{-# TERMINATING #-}
cataI
: {Index : Set}
→ (f : (Index → Set) → (Index → Set))
→ (map : {a b : Index → Set}
→ (∀ i → a i → b i)
→ (i : Index)
→ f a i → f b i)
→ (a : Index → Set)
→ (∀ i → f a i → a i)
→ (i : Index)
→ FixI f i
→ a i
cataI f map a alg i (InI fFix)
= alg i (map (cataI f map a alg) i fFix)
data Index : Set where
TreeIndex
: Index
ForestIndex
: Index
data TreeF (e : Set) (r : Index → Set) : Index → Set where
Node
: e
→ r ForestIndex
→ TreeF e r TreeIndex
Nil
: TreeF e r ForestIndex
Cons
: r TreeIndex
→ r ForestIndex
→ TreeF e r ForestIndex
mapTreeF
: {e : Set}
→ {a b : Index → Set}
→ (∀ i → a i → b i)
→ (i : Index)
→ TreeF e a i
→ TreeF e b i
mapTreeF f TreeIndex (Node e forest)
= Node e (f ForestIndex forest)
mapTreeF _ ForestIndex Nil
= Nil
mapTreeF f ForestIndex (Cons tree forest)
= Cons (f TreeIndex tree) (f ForestIndex forest)
Tree : Set → Set
Tree e = FixI (TreeF e) TreeIndex
Forest : Set → Set
Forest e = FixI (TreeF e) ForestIndex
showTree
: ∀ {e}
→ (e → String)
→ Tree e → String
showTree {e} showE = cataI (TreeF e) mapTreeF (λ _ → String) go TreeIndex
where
go : (i : Index) → TreeF e (λ _ → String) i → String
go TreeIndex (Node e ss)
= "Node " ++ showE e ++ " [" ++ ss ++ "]"
go ForestIndex Nil
= ""
go ForestIndex (Cons s "")
= s
go ForestIndex (Cons s ss)
= s ++ ", " ++ ss
nil : ∀ {e} → Forest e
nil = InI Nil
cons : ∀ {e} → Tree e → Forest e → Forest e
cons tree forest = InI (Cons tree forest)
mkForest : ∀ {e} → List (Tree e) → Forest e
mkForest []
= nil
mkForest (t ∷ ts)
= cons t (mkForest ts)
node : ∀ {e} → e → List (Tree e) → Tree e
node e ts = InI (Node e (mkForest ts))
testShowTree : showTree showℕ (node 1 (node 2 [] ∷ node 3 [] ∷ []))
≡ "Node 1 [Node 2 [], Node 3 []]"
testShowTree = refl
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment