{-# LANGUAGE DataKinds #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE UndecidableInstances #-} module Data.Comp.Term where import "base" Prelude (($), Show (..), Eq (..), Applicative (..)) import Unsafe.Coerce import Control.Monad.Trans.Fresh import Data.Comp.Equality import Data.Comp.Show data Cxt (h :: Bool) f a b i where In :: f a (Cxt h f a b) i -> Cxt h f a b i Hole :: b i -> Cxt True f a b i Var :: a i -> Cxt h f a b i newtype Term f i = Term { unTerm :: ∀ a . Trm f a i } type Trm f a = Cxt False f a (Const ()) toCxt :: Bifunctor (Dual (NT (->))) (NT (->)) (NT (->)) f => Trm f a i -> Cxt h f a b i toCxt = unsafeCoerce instance Functor (NT (->)) (NT (->)) (f a) => Functor (NT (->)) (NT (->)) (Cxt h f a) where map f = NT (\ case Hole x -> Hole (nt f x) Var v -> Var v In t -> In (nt (map (map f :: NT (->) _ _)) t)) instance (Bifunctor (NT (->)) (NT (->)) (NT (->)) f) => Functor (NT (->)) (NT (NT (->))) (Cxt h f) where map f = NT (bimap f (id @(NT (->)))) instance Bifunctor (NT (->)) (NT (->)) (NT (->)) f => Bifunctor (NT (->)) (NT (->)) (NT (->)) (Cxt h f) where bimap f g = NT (\ case Hole x -> Hole (nt g x) Var v -> Var (nt f v) In t -> In (nt (bimap f (bimap f g :: NT (->) _ _)) t)) instance EqH f => EqH (Cxt h f) where eqH (In s) (In t) = eqH s t eqH (Hole x) (Hole y) = peq x y eqH (Var u) (Var v) = peq u v eqH _ _ = pure False instance (EqH f, PEq a) => PEq (Cxt h f Name a) where peq = eqH instance EqH f => Eq (Term f i) where Term x == Term y = evalFresh (eqH x y) instance (Bifunctor (Dual (NT (->))) (NT (->)) (NT (->)) f, ShowH f) => ShowH (Cxt h f) where showH = \ case In t -> showH (bimap (Dual (id @(NT (->)))) (NT (Const . showH)) `nt` t) Var v -> pure $ show v Hole x -> getConst x instance (Bifunctor (Dual (NT (->))) (NT (->)) (NT (->)) f, ShowH f) => Show (Term f i) where show = evalFresh . showH . toCxt . unTerm