module Generic.Core where
open import Generic.Base public
infixr 5 _∷ⁱ_
record AtomUniverse (ℓ : Level) : Type (ℓ-suc ℓ) where
constructor atomUniverse
field
AtomCode : Type₀
Atom : AtomCode → Type ℓ
open AtomUniverse public
data FieldDesc {ℓ} (U : AtomUniverse ℓ) (n : ℕ) : Type₀ where
fieldRec : Fin n → FieldDesc U n
fieldAtom : AtomCode U → FieldDesc U n
data ConDesc {ℓ} (U : AtomUniverse ℓ) (n : ℕ) : Type₀ where
con : List (FieldDesc U n) → ConDesc U n
data TyDesc {ℓ} (U : AtomUniverse ℓ) (n : ℕ) : Type₀ where
dataD : List (ConDesc U n) → TyDesc U n
constructorsOf : ∀ {ℓ n} {U : AtomUniverse ℓ} → TyDesc U n → List (ConDesc U n)
constructorsOf (dataD cs) = cs
data RootDesc {ℓ} (U : AtomUniverse ℓ) (n : ℕ) : Type₀ where
rootData : Fin n → RootDesc U n
rootAtom : AtomCode U → RootDesc U n
pattern μ i = fieldRec i
pattern α a = fieldAtom a
pattern κ₀ = con []
pattern κ₁ a = con (a ∷ [])
pattern κ₂ a b = con (a ∷ b ∷ [])
pattern κ₃ a b c = con (a ∷ b ∷ c ∷ [])
pattern κ₄ a b c d = con (a ∷ b ∷ c ∷ d ∷ [])
pattern κ₅ a b c d e = con (a ∷ b ∷ c ∷ d ∷ e ∷ [])
data ListIx {ℓ} {A : Type ℓ} : List A → Type ℓ where
here : ∀ {x xs} → ListIx (x ∷ xs)
there : ∀ {x xs} → ListIx xs → ListIx (x ∷ xs)
lookup : ∀ {ℓ} {A : Type ℓ} {xs : List A} → ListIx xs → A
lookup (here {x = x}) = x
lookup (there i) = lookup i
pattern ι₀ = here
pattern ι₁ = there ι₀
pattern ι₂ = there ι₁
pattern ι₃ = there ι₂
pattern ι₄ = there ι₃
pattern ι₅ = there ι₄
pattern ι₆ = there ι₅
pattern ι₇ = there ι₆
pattern ι₈ = there ι₇
pattern ι₉ = there ι₈
mutual
data CodeIx {ℓ n} (U : AtomUniverse ℓ) (D : Fin n → TyDesc U n) : TyDesc U n → Type ℓ where
nodeIx : ∀ {cs} (c : ListIx cs) → ArgsCodeIx U D (lookup c) → CodeIx U D (dataD cs)
data FieldCodeIx {ℓ n} (U : AtomUniverse ℓ) (D : Fin n → TyDesc U n) : FieldDesc U n → Type ℓ where
recIx : ∀ {i} → CodeIx U D (D i) → FieldCodeIx U D (fieldRec i)
atomIx : ∀ {a} → Atom U a → FieldCodeIx U D (fieldAtom a)
data ArgsCodeIx {ℓ n} (U : AtomUniverse ℓ) (D : Fin n → TyDesc U n) : ConDesc U n → Type ℓ where
[]ⁱ : ArgsCodeIx U D (con [])
_∷ⁱ_ : ∀ {f fs} → FieldCodeIx U D f → ArgsCodeIx U D (con fs) → ArgsCodeIx U D (con (f ∷ fs))
data RootCodeIx {ℓ n} (U : AtomUniverse ℓ) (D : Fin n → TyDesc U n) : RootDesc U n → Type ℓ where
rootDataIx : ∀ {i} → CodeIx U D (D i) → RootCodeIx U D (rootData i)
rootAtomIx : ∀ {a} → Atom U a → RootCodeIx U D (rootAtom a)
pattern ν₀ c = nodeIx c []ⁱ
pattern ν₁ c a = nodeIx c (a ∷ⁱ []ⁱ)
pattern ν₂ c a b = nodeIx c (a ∷ⁱ b ∷ⁱ []ⁱ)
pattern ν₃ c a b d = nodeIx c (a ∷ⁱ b ∷ⁱ d ∷ⁱ []ⁱ)
pattern ν₄ c a b d e = nodeIx c (a ∷ⁱ b ∷ⁱ d ∷ⁱ e ∷ⁱ []ⁱ)
pattern ν₅ c a b d e f = nodeIx c (a ∷ⁱ b ∷ⁱ d ∷ⁱ e ∷ⁱ f ∷ⁱ []ⁱ)
record Generic {ℓ} (U : AtomUniverse ℓ) (A : Type ℓ) : Type (ℓ-suc ℓ) where
constructor generic
field
typeCount : ℕ
desc : Fin typeCount → TyDesc U typeCount
root : RootDesc U typeCount
typeNames : Fin typeCount → String
constructorNames : Fin typeCount → List String
encode : A → RootCodeIx U desc root
decode : RootCodeIx U desc root → A
decode-encode : (x : A) → decode (encode x) ≡ x
encode-decode : (x : RootCodeIx U desc root) → encode (decode x) ≡ x
asIso : Iso A (RootCodeIx U desc root)
asIso = iso encode decode encode-decode decode-encode
encode-injective : ∀ {x y} → encode x ≡ encode y → x ≡ y
encode-injective {x} {y} p =
sym (decode-encode x) ∙ cong decode p ∙ decode-encode y
decode-injective : ∀ {x y} → decode x ≡ decode y → x ≡ y
decode-injective {x} {y} p =
sym (encode-decode x) ∙ cong encode p ∙ encode-decode y
encode-preimage : (x : RootCodeIx U desc root) → Σ[ y ∈ A ] encode y ≡ x
encode-preimage x = decode x , encode-decode x
decode-preimage : (x : A) → Σ[ y ∈ RootCodeIx U desc root ] decode y ≡ x
decode-preimage x = encode x , decode-encode x
InferredGeneric : ∀ {ℓ} → Type ℓ → Type (ℓ-suc ℓ)
InferredGeneric {ℓ} A = Σ[ U ∈ AtomUniverse ℓ ] Generic U A
singletonAtomUniverse : ∀ {ℓ} → Type ℓ → AtomUniverse ℓ
singletonAtomUniverse A = atomUniverse Unit (λ _ → A)
data BuiltinAtomCode : Type₀ where
natAtom stringAtom boolAtom unitAtom : BuiltinAtomCode
BuiltinAtom : BuiltinAtomCode → Type₀
BuiltinAtom natAtom = ℕ
BuiltinAtom stringAtom = String
BuiltinAtom boolAtom = Bool
BuiltinAtom unitAtom = Unit
BuiltinAtoms : AtomUniverse ℓ-zero
BuiltinAtoms = atomUniverse BuiltinAtomCode BuiltinAtom
atomicGeneric : ∀ {ℓ} (U : AtomUniverse ℓ) (a : AtomCode U) → Generic U (Atom U a)
atomicGeneric U a =
generic
zero
(λ ())
(rootAtom a)
(λ ())
(λ ())
(λ x → rootAtomIx x)
(λ { (rootAtomIx x) → x })
(λ _ → refl)
(λ { (rootAtomIx _) → refl })
inferAtomicGeneric : ∀ {ℓ} {A : Type ℓ} → InferredGeneric A
inferAtomicGeneric {A = A} = singletonAtomUniverse A , atomicGeneric (singletonAtomUniverse A) tt
withAtomUniverse : ∀ {ℓ} (U : AtomUniverse ℓ) {A : Type ℓ} → Generic U A → Generic U A
withAtomUniverse U g = g