module Data.Rewriting.Term.Ops (
funs,
funsDL,
vars,
varsDL,
root,
withArity,
subtermAt,
properSubterms,
subterms,
replaceAt,
rename,
isVar,
isFun,
isGround,
isLinear,
isInstanceOf,
isVariantOf,
) where
import Data.Rewriting.Pos
import Data.Rewriting.Term.Type as Term
import Data.Rewriting.Substitution.Match
import Data.Maybe
import qualified Data.MultiSet as MS
import Control.Monad (guard)
withArity :: Term f v -> Term (f, Int) v
withArity = Term.fold Var (\f ts -> Fun (f, length ts) ts)
subtermAt :: Term f v -> Pos -> Maybe (Term f v)
subtermAt t [] = Just t
subtermAt (Fun _ ts) (p:ps) | p >= 0 && p < length ts = subtermAt (ts !! p) ps
subtermAt _ _ = Nothing
properSubterms :: Term f v -> [Term f v]
properSubterms (Var _) = []
properSubterms (Fun _ ts) = concatMap subterms ts
subterms :: Term f v -> [Term f v]
subterms t = t : properSubterms t
replaceAt :: Term f v -> Pos -> Term f v -> Maybe (Term f v)
replaceAt _ [] t' = Just t'
replaceAt (Fun f ts) (i:p) t' = do
guard (i >= 0 && i < length ts)
let (ts1, t:ts2) = splitAt i ts
t <- replaceAt t p t'
return $ Fun f (ts1 ++ t : ts2)
replaceAt _ _ _ = Nothing
vars :: Term f v -> [v]
vars = flip varsDL []
varsDL :: Term f v -> [v] -> [v]
varsDL = Term.fold (:) (const $ foldr (.) id)
root :: Term f v -> Either v f
root (Fun f _) = Right f
root (Var v) = Left v
funs :: Term f v -> [f]
funs = flip funsDL []
funsDL :: Term f v -> [f] -> [f]
funsDL = Term.fold (const id) (\f xs -> (f:) . foldr (.) id xs)
isVar :: Term f v -> Bool
isVar Var{} = True
isVar Fun{} = False
isFun :: Term f v -> Bool
isFun Var{} = False
isFun Fun{} = True
isGround :: Term f v -> Bool
isGround = null . vars
isLinear :: Ord v => Term f v -> Bool
isLinear = all (\(_, c) -> c == 1) . MS.toOccurList . MS.fromList . vars
isInstanceOf :: (Eq f, Ord v, Ord v') => Term f v -> Term f v' -> Bool
isInstanceOf t u = isJust (match u t)
isVariantOf :: (Eq f, Ord v, Ord v') => Term f v -> Term f v' -> Bool
isVariantOf t u = isInstanceOf t u && isInstanceOf u t
rename :: (v -> v') -> Term f v -> Term f v'
rename = Term.map id