Source code on Github
{-# OPTIONS --safe #-}
module Prelude.Generics.Deriving where
open import Prelude.Init; open Meta
open import Prelude.Functor
open import Prelude.Monad
open import Prelude.Lift
open import Prelude.General
open import Prelude.FromList; open import Prelude.ToList
open import Prelude.Generics.Core
Derivation : ℕ → Set
Derivation n =
  List ( Name       
       × (Name ^ n) 
       )
       → TC ⊤ 
record Derivable (F : String) (n : ℕ) : Setω where
  field derive : Derivation (Nat.pred n)
open Derivable ⦃...⦄ public
private
  isOmegaKind : Type → Bool
  isOmegaKind = λ where
    (agda-sort s) → case s of λ where
      (inf _) → true
      _ → false
    _ → false
  `ωkindOf : Term → TC Type
  `ωkindOf e = do
    ty ← inferType e
    ki ← inferType ty
    return $
      if isOmegaKind ki then ty
      else quote ↑ω_ ∙⟦ ty ⟧
  removeQualifiers : String → String
  removeQualifiers = fromList
                   ∘ L.reverse ∘ takeWhile (¬? ∘ ('.' Ch.≟_)) ∘ L.reverse
                   ∘ toList
  `toString : Name → Term
  `toString = lit ∘′ string ∘ removeQualifiers ∘ Meta.Show.showName
macro
  DERIVE : Name → Tactic
  DERIVE n hole = do
    ty ← `ωkindOf =<< getType n
    unify hole $ def (quote derive) [ hArg (`toString n) ]
  DERIVABLE : Name → Tactic
  DERIVABLE n = flip unify (quote Derivable ∙⟦ `toString n ⟧)
private
  record X₀ (A : Set) : Set where
    field x₀ : A
  open X₀ ⦃...⦄
  record X (A : Set ℓ) : Set ℓ where
    field x : A
  open X ⦃...⦄
  record Y₀ (A : Set) ⦃ _ : X₀ A ⦄ : Set where
    field eq₀ : x₀ ≡ x₀
  open Y₀ ⦃...⦄
  record Y (A : Set ℓ) ⦃ _ : X A ⦄ : Set ℓ where
    field eq : x ≡ x
  open Y ⦃...⦄
  record ∅ : Set where
  open ∅ ⦃...⦄
  _ : ∀ {ℓ} → Set ℓ → Set ℓ
  _ = X
  _ : ∀ {ℓ} → (A : Set ℓ) ⦃ _ : X A ⦄ → Set ℓ
  _ = Y
  _ : Set
  _ = ∅
  instance
    _ : DERIVABLE X 1
    _ = λ where .derive → λ where
      ((n , f) ∷ []) → do
        declareDef (vArg f) (n ∙)
        defineFun f [ clause [] [] (lit $′ nat 0) ]
      _ → return tt
  unquoteDecl X-ℕ = DERIVE X [ quote ℕ , X-ℕ ]
  _ : ℕ
  _ = X-ℕ
  module _
    ⦃ _ : DERIVABLE Y 1 ⦄
    ⦃ _ : DERIVABLE X₀ 1 ⦄
    ⦃ _ : DERIVABLE Y₀ 1 ⦄
    ⦃ _ : DERIVABLE ∅ 0 ⦄
    where
    _ : List (Derivation 0)
    _ = DERIVE X
      ∷ DERIVE Y
      ∷ DERIVE X₀
      ∷ DERIVE Y₀
      ∷ DERIVE ∅
      ∷ []