{-# LANGUAGE ConstraintKinds
, DataKinds
, DefaultSignatures
, DerivingVia
, EmptyCase
, FlexibleContexts
, FlexibleInstances
, InstanceSigs
, MultiParamTypeClasses
, PartialTypeSignatures
, StandaloneDeriving
, TupleSections
, TypeOperators
#-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Language.Nominal.Sub
(
KSub (..)
, Sub
)
where
import GHC.Generics
import Type.Reflection
import Data.List.NonEmpty (NonEmpty)
import Language.Nominal.Name
import Language.Nominal.Binder
import Language.Nominal.Abs
class KSub n x y where
sub :: n -> x -> y -> y
default sub :: (Generic y, GSub n x (Rep y)) => n -> x -> y -> y
sub n x = to . gsub n x . from
type Sub n x y = KSub (KName Tom n) x y
instance KSub n x (Nameless a) where
sub _ _ = id
deriving via Nameless () instance KSub n x ()
deriving via Nameless Bool instance KSub n x Bool
deriving via Nameless Char instance KSub n x Char
deriving via Nameless Int instance KSub n x Int
deriving via Nameless Integer instance KSub n x Integer
instance (KSub n x a, KSub n x b) => KSub n x (a, b)
instance (KSub n x a, KSub n x b, KSub n x c) => KSub n x (a, b, c)
instance (KSub n x a, KSub n x b, KSub n x c, KSub n x d) => KSub n x (a, b, c, d)
instance (KSub n x a, KSub n x b, KSub n x c, KSub n x d, KSub n x e) => KSub n x (a, b, c, d, e)
instance KSub n x a => KSub n x [a]
instance KSub n x a => KSub n x (NonEmpty a)
instance KSub n x a => KSub n x (Maybe a)
instance (KSub n x a, KSub n x b) => KSub n x (Either a b)
instance KSub (KName s n) (KName s n) (KName s n) where
sub n n' a = if a == n then n' else a
instance {-# INCOHERENT #-} (Typeable s, Swappable n, Swappable x, Swappable y, KSub (KName s n) x y) => BinderConc (KAbs (KName s n) y) (KName s n) y s x where
conc y' x = y' @@! \n -> sub n x
instance (Typeable s, Typeable u, KSub (KName s n) x t, KSub (KName s n) x y, Swappable t, Swappable y) =>
KSub (KName s n) x (KAbs (KName u t) y) where
sub n x = genApp $ \n' y -> (sub n x <$> n') @> sub n x y
instance Eq n => KSub n ((n -> a) -> a) (n -> a) where
sub n x ctx n' = if n' == n then x ctx else ctx n'
instance Eq n => KSub n ((n -> a) -> a) ((n -> a) -> a) where
sub n x x' ctx = x' (sub n x ctx)
class GSub n x f where
gsub :: n -> x -> f w -> f w
instance (GSub n x f, GSub n x g) => GSub n x (f :*: g) where
gsub n x (y :*: z) = gsub n x y :*: gsub n x z
instance GSub n x U1 where
gsub _ _ = id
instance GSub n x V1 where
gsub _ _ y = case y of
instance GSub n x f => GSub n x (M1 i t f) where
gsub n x = M1 . gsub n x . unM1
instance KSub n x c => GSub n x (K1 i c) where
gsub n x = K1 . sub n x . unK1
instance (GSub n x f, GSub n x g) => GSub n x (f :+: g) where
gsub n x (L1 y) = L1 $ gsub n x y
gsub n x (R1 z) = R1 $ gsub n x z