module Nominal.Type where
import Data.Map (Map, findWithDefault)
import Data.Set (Set, empty, insert)
import Nominal.Formula
import Nominal.Formula.Operators (foldFormulaVariables, mapFormulaVariables)
import Nominal.Variable (Variable)
import Nominal.Variants (Variants, fromList, map, mapWithMono, prodWithMono, toList, variant, variantsRelation)
import Prelude hiding (and, map, not, or)
import GHC.Generics
data Scope
= All
| Free
type MapVarFun = (Scope, Variable -> Variable)
type FoldVarFun b = (Scope, Variable -> b -> b)
class BareNominalType a where
eq :: a -> a -> Formula
variants :: a -> Variants a
mapVariables :: MapVarFun -> a -> a
foldVariables :: FoldVarFun b -> b -> a -> b
default eq :: (Generic a, GBareNominalType (Rep a)) => a -> a -> Formula
eq x y = geq (from x) (from y)
default variants :: (Generic a, GBareNominalType (Rep a)) => a -> Variants a
variants x = mapWithMono to $ gvariants (from x)
default mapVariables :: (Generic a, GBareNominalType (Rep a)) => MapVarFun -> a -> a
mapVariables f x = to (gmapVariables f (from x))
default foldVariables :: (Generic a, GBareNominalType (Rep a)) => FoldVarFun b -> b -> a -> b
foldVariables f b x = gfoldVariables f b (from x)
type NominalType a = (Ord a, BareNominalType a)
neq :: BareNominalType a => a -> a -> Formula
neq x1 x2 = not $ eq x1 x2
collectWith :: (BareNominalType a, Ord b) => (Variable -> Maybe b) -> a -> Set b
collectWith cf = foldVariables (All, maybe id insert . cf) empty
getAllVariables :: BareNominalType a => a -> Set Variable
getAllVariables = foldVariables (All, insert) empty
freeVariables :: BareNominalType a => a -> Set Variable
freeVariables = foldVariables (Free, insert) empty
mapVariablesIf :: BareNominalType a => (Variable -> Bool) -> (Variable -> Variable) -> a -> a
mapVariablesIf cf mf = mapVariables (All, \v -> if cf v then mf v else v)
replaceVariables :: BareNominalType a => Map Variable Variable -> a -> a
replaceVariables varsMap = mapVariables (All, \var -> findWithDefault var var varsMap)
instance BareNominalType Variable where
eq = equals
variants = variant
mapVariables (_, f) = f
foldVariables (_, f) acc v = f v acc
instance BareNominalType Formula where
eq = iff
variants = variant
mapVariables (_, f) = mapFormulaVariables f
foldVariables (_, f) = foldFormulaVariables f
instance (Ord a, BareNominalType a) => BareNominalType (Variants a) where
eq = variantsRelation eq
variants = map variant
mapVariables f = fromList . mapVariables f . toList
foldVariables f acc = foldl (foldVariables f) acc . toList
#define NOM_INSTANCE(foo) \
instance BareNominalType foo where; \
eq x y = fromBool (x == y); \
variants = variant; \
mapVariables _ = id; \
foldVariables _ acc _ = acc; \
NOM_INSTANCE(Bool)
NOM_INSTANCE(Char)
NOM_INSTANCE(Double)
NOM_INSTANCE(Float)
NOM_INSTANCE(Int)
NOM_INSTANCE(Integer)
NOM_INSTANCE(Ordering)
instance BareNominalType ()
instance BareNominalType a => BareNominalType [a]
instance BareNominalType a => BareNominalType (Maybe a)
instance (BareNominalType a, BareNominalType b) => BareNominalType (Either a b)
instance (BareNominalType a, BareNominalType b) => BareNominalType (a, b)
instance (BareNominalType a, BareNominalType b, BareNominalType c) => BareNominalType (a, b, c)
instance (BareNominalType a, BareNominalType b, BareNominalType c, BareNominalType d) => BareNominalType (a, b, c, d)
instance (BareNominalType a, BareNominalType b, BareNominalType c, BareNominalType d, BareNominalType e) => BareNominalType (a, b, c, d, e)
instance (BareNominalType a, BareNominalType b, BareNominalType c, BareNominalType d, BareNominalType e, BareNominalType f) => BareNominalType (a, b, c, d, e, f)
instance (BareNominalType a, BareNominalType b, BareNominalType c, BareNominalType d, BareNominalType e, BareNominalType f, BareNominalType g) => BareNominalType (a, b, c, d, e, f, g)
class GBareNominalType f where
geq :: f a -> f a -> Formula
gvariants :: f a -> Variants (f a)
gmapVariables :: MapVarFun -> f a -> f a
gfoldVariables :: FoldVarFun b -> b -> f a -> b
instance GBareNominalType V1 where
geq _ _ = true
gvariants = variant
gmapVariables _ = id
gfoldVariables _ acc _ = acc
instance GBareNominalType U1 where
geq _ _ = true
gvariants = variant
gmapVariables _ = id
gfoldVariables _ acc _ = acc
instance BareNominalType c => GBareNominalType (K1 i c) where
geq (K1 a) (K1 b) = eq a b
gvariants (K1 a) = mapWithMono K1 $ variants a
gmapVariables f (K1 a) = K1 $ mapVariables f a
gfoldVariables f b (K1 a) = foldVariables f b a
instance GBareNominalType a => GBareNominalType (M1 i c a) where
geq (M1 a) (M1 b) = geq a b
gvariants (M1 a) = mapWithMono M1 $ gvariants a
gmapVariables f (M1 a) = M1 $ gmapVariables f a
gfoldVariables f b (M1 a) = gfoldVariables f b a
instance (GBareNominalType a, GBareNominalType b) => GBareNominalType (a :+: b) where
geq (L1 a) (L1 b) = geq a b
geq (R1 a) (R1 b) = geq a b
geq _ _ = false
gvariants (L1 a) = mapWithMono L1 $ gvariants a
gvariants (R1 a) = mapWithMono R1 $ gvariants a
gmapVariables f (L1 a) = L1 $ gmapVariables f a
gmapVariables f (R1 a) = R1 $ gmapVariables f a
gfoldVariables f b (L1 a) = gfoldVariables f b a
gfoldVariables f b (R1 a) = gfoldVariables f b a
instance (GBareNominalType a, GBareNominalType b) => GBareNominalType (a :*: b) where
geq (a1 :*: b1) (a2 :*: b2) = geq a1 a2 /\ geq b1 b2
gvariants (a :*: b) = prodWithMono (:*:) (gvariants a) (gvariants b)
gmapVariables f (a :*: b) = gmapVariables f a :*: gmapVariables f b
gfoldVariables f c (a :*: b) = gfoldVariables f (gfoldVariables f c a) b