twee-2.0: src/Twee/Base.hs
{-# LANGUAGE TypeFamilies, FlexibleInstances, UndecidableInstances, DeriveFunctor, DefaultSignatures, FlexibleContexts, DeriveGeneric, TypeOperators, MultiParamTypeClasses, GeneralizedNewtypeDeriving, ConstraintKinds, RecordWildCards #-}
-- To suppress a warning about hiding Arity
{-# OPTIONS_GHC -fno-warn-dodgy-imports #-}
module Twee.Base(
Id(..), Symbolic(..), subst, GSymbolic(..), Has(..), terms, TermOf, TermListOf, SubstOf, TriangleSubstOf, BuilderOf, FunOf,
vars, isGround, funs, occ, occVar, canonicalise, renameAvoiding,
Minimal(..), minimalTerm, isMinimal, erase,
Skolem(..), Arity(..), Sized(..), Ordered(..), lessThan, orientTerms, Equals(..), Strictness(..), Function, Extended(..),
module Twee.Term, module Twee.Pretty) where
import Prelude hiding (lookup)
import Control.Monad
import qualified Data.DList as DList
import Twee.Term hiding (subst, canonicalise)
import qualified Twee.Term as Term
import Twee.Pretty
import Twee.Constraints hiding (funs)
import Data.DList(DList)
import GHC.Generics hiding (Arity)
import Data.Typeable
import Data.Int
import Data.Maybe
import qualified Data.IntMap.Strict as IntMap
-- Represents a unique identifier (e.g., for a rule).
newtype Id = Id { unId :: Int32 }
deriving (Eq, Ord, Show, Enum, Bounded, Num, Real, Integral)
instance Pretty Id where
pPrint = text . show . unId
-- Generalisation of term functionality to things that contain terms.
class Symbolic a where
type ConstantOf a
termsDL :: a -> DList (TermListOf a)
default termsDL :: (Generic a, GSymbolic (ConstantOf a) (Rep a)) => a -> DList (TermListOf a)
termsDL = gtermsDL . from
subst_ :: (Var -> BuilderOf a) -> a -> a
default subst_ :: (Generic a, GSymbolic (ConstantOf a) (Rep a)) => (Var -> BuilderOf a) -> a -> a
subst_ sub = to . gsubst sub . from
class GSymbolic k f where
gtermsDL :: f a -> DList (TermList k)
gsubst :: (Var -> Builder k) -> f a -> f a
instance GSymbolic k V1 where
gtermsDL _ = undefined
gsubst _ x = x
instance GSymbolic k U1 where
gtermsDL _ = mzero
gsubst _ x = x
instance (GSymbolic k f, GSymbolic k g) => GSymbolic k (f :*: g) where
gtermsDL (x :*: y) = gtermsDL x `mplus` gtermsDL y
gsubst sub (x :*: y) = gsubst sub x :*: gsubst sub y
instance (GSymbolic k f, GSymbolic k g) => GSymbolic k (f :+: g) where
gtermsDL (L1 x) = gtermsDL x
gtermsDL (R1 x) = gtermsDL x
gsubst sub (L1 x) = L1 (gsubst sub x)
gsubst sub (R1 x) = R1 (gsubst sub x)
instance GSymbolic k f => GSymbolic k (M1 i c f) where
gtermsDL (M1 x) = gtermsDL x
gsubst sub (M1 x) = M1 (gsubst sub x)
instance (Symbolic a, ConstantOf a ~ k) => GSymbolic k (K1 i a) where
gtermsDL (K1 x) = termsDL x
gsubst sub (K1 x) = K1 (subst_ sub x)
subst :: (Symbolic a, Substitution s, SubstFun s ~ ConstantOf a) => s -> a -> a
subst sub x = subst_ (evalSubst sub) x
terms :: Symbolic a => a -> [TermListOf a]
terms = DList.toList . termsDL
type TermOf a = Term (ConstantOf a)
type TermListOf a = TermList (ConstantOf a)
type SubstOf a = Subst (ConstantOf a)
type TriangleSubstOf a = TriangleSubst (ConstantOf a)
type BuilderOf a = Builder (ConstantOf a)
type FunOf a = Fun (ConstantOf a)
instance Symbolic (Term f) where
type ConstantOf (Term f) = f
termsDL = return . singleton
subst_ sub = build . Term.subst sub
instance Symbolic (TermList f) where
type ConstantOf (TermList f) = f
termsDL = return
subst_ sub = buildList . Term.substList sub
instance Symbolic (Subst f) where
type ConstantOf (Subst f) = f
termsDL (Subst sub) = termsDL (IntMap.elems sub)
subst_ sub (Subst s) = Subst (fmap (subst_ sub) s)
instance (ConstantOf a ~ ConstantOf b, Symbolic a, Symbolic b) => Symbolic (a, b) where
type ConstantOf (a, b) = ConstantOf a
instance (ConstantOf a ~ ConstantOf b,
ConstantOf a ~ ConstantOf c,
Symbolic a, Symbolic b, Symbolic c) => Symbolic (a, b, c) where
type ConstantOf (a, b, c) = ConstantOf a
instance Symbolic a => Symbolic [a] where
type ConstantOf [a] = ConstantOf a
instance Symbolic a => Symbolic (Maybe a) where
type ConstantOf (Maybe a) = ConstantOf a
class Has a b where
the :: a -> b
instance Has a a where
the = id
{-# INLINE vars #-}
vars :: Symbolic a => a -> [Var]
vars x = [ v | t <- DList.toList (termsDL x), Var v <- subtermsList t ]
{-# INLINE isGround #-}
isGround :: Symbolic a => a -> Bool
isGround = null . vars
{-# INLINE funs #-}
funs :: Symbolic a => a -> [FunOf a]
funs x = [ f | t <- DList.toList (termsDL x), App f _ <- subtermsList t ]
{-# INLINE occ #-}
occ :: Symbolic a => FunOf a -> a -> Int
occ x t = length (filter (== x) (funs t))
{-# INLINE occVar #-}
occVar :: Symbolic a => Var -> a -> Int
occVar x t = length (filter (== x) (vars t))
{-# INLINEABLE canonicalise #-}
canonicalise :: Symbolic a => a -> a
canonicalise t = subst sub t
where
sub = Term.canonicalise (DList.toList (termsDL t))
{-# INLINEABLE renameAvoiding #-}
renameAvoiding :: (Symbolic a, Symbolic b) => a -> b -> b
renameAvoiding x y =
subst (\(V x) -> var (V (x+n))) y
where
V n = maximum (V 0:map boundList (terms x))
isMinimal :: Minimal f => Term f -> Bool
isMinimal (App f Empty) | f == minimal = True
isMinimal _ = False
minimalTerm :: Minimal f => Term f
minimalTerm = build (con minimal)
erase :: (Symbolic a, ConstantOf a ~ f, Minimal f) => [Var] -> a -> a
erase [] t = t
erase xs t = subst sub t
where
sub = fromMaybe undefined $ flattenSubst [(x, minimalTerm) | x <- xs]
class Skolem f where
skolem :: Var -> Fun f
class Arity f where
arity :: f -> Int
instance Arity f => Arity (Fun f) where
arity = arity . fun_value
class Sized a where
size :: a -> Int
instance Sized f => Sized (Fun f) where
size = size . fun_value
instance Sized f => Sized (TermList f) where
size = aux 0
where
aux n Empty = n
aux n (ConsSym (App f _) t) = aux (n+size f) t
aux n (Cons (Var _) t) = aux (n+1) t
instance Sized f => Sized (Term f) where
size = size . singleton
type Function f = (Ordered f, Arity f, Sized f, Minimal f, Skolem f, PrettyTerm f, Equals f)
class Equals f where
equalsCon, trueCon, falseCon :: Fun f
data Extended f =
Minimal
| Skolem Var
| Function f
| EqualsCon | TrueCon | FalseCon
deriving (Eq, Ord, Show, Functor)
instance Pretty f => Pretty (Extended f) where
pPrintPrec _ _ Minimal = text "?"
pPrintPrec _ _ (Skolem (V n)) = text "sk" <> pPrint n
pPrintPrec l p (Function f) = pPrintPrec l p f
pPrintPrec _ _ EqualsCon = text "$equals"
pPrintPrec _ _ TrueCon = text "$true"
pPrintPrec _ _ FalseCon = text "$false"
instance PrettyTerm f => PrettyTerm (Extended f) where
termStyle (Function f) = termStyle f
termStyle _ = uncurried
instance Sized f => Sized (Extended f) where
size (Function f) = size f
size EqualsCon = 0
size TrueCon = 0
size FalseCon = 0
size _ = 1
instance Arity f => Arity (Extended f) where
arity (Function f) = arity f
arity EqualsCon = 2
arity _ = 0
instance (Typeable f, Ord f) => Minimal (Extended f) where
minimal = fun Minimal
instance (Typeable f, Ord f) => Skolem (Extended f) where
skolem x = fun (Skolem x)
instance (Typeable f, Ord f) => Equals (Extended f) where
equalsCon = fun EqualsCon
trueCon = fun TrueCon
falseCon = fun FalseCon