{-# LANGUAGE ConstraintKinds
, DataKinds
, DefaultSignatures
, DerivingVia
, EmptyCase
, FlexibleContexts
, FlexibleInstances
, GADTs
, InstanceSigs
, MultiParamTypeClasses
, PartialTypeSignatures
, ScopedTypeVariables
, StandaloneDeriving
, TupleSections
, TypeOperators
#-}
module Language.Nominal.NameSet
(
KSupport (..)
, Support
, supp
, kapart
, apart
, atomPoint
, namePoint
, KRestrict (..)
, Restrict
, restrictN
) where
import Data.Proxy (Proxy (..))
import Data.Type.Equality
import Type.Reflection
import Data.List.NonEmpty (NonEmpty)
import Data.Set (Set)
import qualified Data.Set as S
import GHC.Generics
import Language.Nominal.Name
import Language.Nominal.Utilities
class (Typeable s, Swappable a) => KSupport s a where
ksupp :: proxy s -> a -> Set (KAtom s)
default ksupp :: (Generic a, GSupport s (Rep a)) => proxy s -> a -> Set (KAtom s)
ksupp _ = gsupp . from
type Support a = KSupport Tom a
supp :: Support a => a -> Set Atom
supp = ksupp atTom
instance Typeable s => KSupport s (Nameless a) where
ksupp _ _ = S.empty
deriving via Nameless () instance Typeable s => KSupport s ()
deriving via Nameless Bool instance Typeable s => KSupport s Bool
deriving via Nameless Char instance Typeable s => KSupport s Char
deriving via Nameless Int instance Typeable s => KSupport s Int
instance (Typeable s, Typeable t) => KSupport s (KAtom t) where
ksupp _ a = case testEquality (typeRep :: TypeRep s) (typeRep :: TypeRep t) of
Nothing -> S.empty
Just Refl -> S.singleton a
instance (Typeable s, Typeable u, KSupport s t) => KSupport s (KName u t) where
ksupp p a = ksupp p $ (nameAtom a, nameLabel a)
instance KSupport s a => KSupport s (Maybe a)
instance KSupport s a => KSupport s [a]
instance KSupport s a => KSupport s (NonEmpty a)
instance (Ord a, KSupport s a) => KSupport s (S.Set a) where
ksupp p = foldMap $ ksupp p
instance (KSupport s a, KSupport s b) => KSupport s (a, b)
instance (KSupport s a, KSupport s b, KSupport s c) => KSupport s (a, b, c)
instance (KSupport s a, KSupport s b, KSupport s c, KSupport s d) => KSupport s (a, b, c, d)
instance (KSupport s a, KSupport s b, KSupport s c, KSupport s d, KSupport s e) => KSupport s (a, b, c, d, e)
instance (KSupport s a, KSupport s b) => KSupport s (Either a b)
kapart :: (KSupport s a, KSupport s b) => proxy s -> a -> b -> Bool
kapart p a b = (ksupp p a) `S.disjoint` (ksupp p b)
apart :: (Support a, Support b) => a -> b -> Bool
apart = kapart atTom
atomPoint :: (Foldable f, KSupport s a) => KAtom s -> f a -> NonEmpty a
atomPoint a = point $ S.member a . ksupp Proxy
namePoint :: (Foldable f, KSupport s a) => KName s t -> f a -> NonEmpty a
namePoint = atomPoint . nameAtom
class (Typeable s, Swappable a) => KRestrict s a where
restrict :: [KAtom s] -> a -> a
type Restrict = KRestrict Tom
restrictN :: KRestrict s a => [KName s t] -> a -> a
restrictN l = restrict (nameAtom <$> l)
instance Typeable s => KRestrict s (Nameless a) where
restrict _ = id
deriving via Nameless Bool instance Typeable s => KRestrict s Bool
deriving via Nameless Int instance Typeable s => KRestrict s Int
deriving via Nameless () instance Typeable s => KRestrict s ()
deriving via Nameless Char instance Typeable s => KRestrict s Char
instance KRestrict s a => KRestrict s (Maybe a) where
restrict atms a = restrict atms <$> a
instance KSupport s a => KRestrict s [a] where
restrict atms as = filter (kapart (Proxy :: Proxy s) atms) as
instance (Ord a, KSupport s a) => KRestrict s (S.Set a) where
restrict atms as = S.filter (kapart (Proxy :: Proxy s) atms) as
class GSupport s f where
gsupp :: f x -> Set (KAtom s)
instance GSupport s V1 where
gsupp x = case x of
instance GSupport s U1 where
gsupp U1 = S.empty
instance GSupport s f => GSupport s (M1 i t f) where
gsupp = gsupp . unM1
instance KSupport s c => GSupport s (K1 i c) where
gsupp = ksupp Proxy . unK1
instance (GSupport s f, GSupport s g) => GSupport s (f :*: g) where
gsupp (x :*: y) = gsupp x `S.union` gsupp y
instance (GSupport s f, GSupport s g) => GSupport s (f :+: g) where
gsupp (L1 x) = gsupp x
gsupp (R1 y) = gsupp y