------------------------------------------------------------------------------------------- --- Substitution abilities ------------------------------------------------------------------------------------------- {-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, UndecidableInstances #-} module CHR.Data.Substitutable ( VarUpdatable(..) , VarExtractable(..) , ExtrValVarKey , VarTerm(..) ) where import qualified Data.Set as Set import CHR.Data.VarMp ------------------------------------------------------------------------------------------- --- Misc ------------------------------------------------------------------------------------------- infixr 6 `varUpd` infixr 6 `varUpdCyc` -- | The variable wich is used as a key into a substitution type family ExtrValVarKey vv :: * ------------------------------------------------------------------------------------------- --- Updatable ------------------------------------------------------------------------------------------- -- | Term in which variables can be updated with a subst(itution) class VarUpdatable vv subst where -- | Update varUpd :: subst -> vv -> vv -- s `varUpd` x = let (x',_) = s `varUpdCyc` x in x -- {-# INLINE varUpd #-} -- | Update with cycle detection varUpdCyc :: subst -> vv -> (vv, VarMp' (VarLookupKey subst) (VarLookupVal subst)) s `varUpdCyc` x = (s `varUpd` x, emptyVarMp) {-# INLINE varUpdCyc #-} instance {-# OVERLAPPABLE #-} VarUpdatable vv subst => VarUpdatable (Maybe vv) subst where s `varUpd` m = fmap (s `varUpd`) m s `varUpdCyc` (Just x) = let (x',cm) = s `varUpdCyc` x in (Just x', cm) s `varUpdCyc` Nothing = (Nothing, emptyVarMp) instance {-# OVERLAPPABLE #-} (Ord (VarLookupKey subst), VarUpdatable vv subst) => VarUpdatable [vv] subst where s `varUpd` l = map (s `varUpd`) l s `varUpdCyc` l = let (l',cms) = unzip $ map (s `varUpdCyc`) l in (l', varmpUnions cms) ------------------------------------------------------------------------------------------- --- Extractibility of free vars ------------------------------------------------------------------------------------------- -- | Term from which free variables can be extracted class Ord (ExtrValVarKey vv) => VarExtractable vv where -- | Free vars, as a list varFree :: vv -> [ExtrValVarKey vv] varFree = Set.toList . varFreeSet -- | Free vars, as a set varFreeSet :: vv -> Set.Set (ExtrValVarKey vv) varFreeSet = Set.fromList . varFree type instance ExtrValVarKey (Maybe vv) = ExtrValVarKey vv instance {-# OVERLAPPABLE #-} (VarExtractable vv, Ord (ExtrValVarKey vv)) => VarExtractable (Maybe vv) where varFreeSet = maybe Set.empty varFreeSet type instance ExtrValVarKey [vv] = ExtrValVarKey vv instance {-# OVERLAPPABLE #-} (VarExtractable vv, Ord (ExtrValVarKey vv)) => VarExtractable [vv] where varFreeSet = Set.unions . map varFreeSet ------------------------------------------------------------------------------------------- --- Is a term with a variable which we can observe and construct ------------------------------------------------------------------------------------------- -- | Term with a (substitutable, extractable, free, etc.) variable class VarTerm vv where -- | Maybe is a key varTermMbKey :: vv -> Maybe (ExtrValVarKey vv) -- | Construct wrapper for key (i.e. lift, embed) varTermMkKey :: ExtrValVarKey vv -> vv