ideas-0.6: src/Common/Rewriting/Term.hs
{-# LANGUAGE TypeSynonymInstances, DeriveDataTypeable #-}
-----------------------------------------------------------------------------
-- Copyright 2010, Open Universiteit Nederland. This file is distributed
-- under the terms of the GNU General Public License. For more information,
-- see the file "LICENSE.txt", which is included in the distribution.
-----------------------------------------------------------------------------
-- |
-- Maintainer : bastiaan.heeren@ou.nl
-- Stability : provisional
-- Portability : portable (depends on ghc)
--
-- A simple data type for term rewriting
--
-----------------------------------------------------------------------------
module Common.Rewriting.Term where
import Common.Utils (ShowString(..))
import Common.Uniplate
import Control.Monad
import Common.Rewriting.MetaVar
import Data.Typeable
-----------------------------------------------------------
-- * Data type for terms
data Symbol = S (Maybe String) String
deriving (Eq, Ord)
data Term = Var String
| Con Symbol
| App Term Term
| Num Integer
| Float Double
| Meta Int
deriving (Show, Eq, Ord, Typeable)
instance Show Symbol where
show (S ma b) = maybe b (\a -> a++ "." ++ b) ma
instance MetaVar Term where
metaVar = Meta
isMetaVar (Meta n) = Just n
isMetaVar _ = Nothing
instance Uniplate Term where
uniplate (App f a) = ([f,a], \[g,b] -> App g b)
uniplate term = ([], \_ -> term)
-----------------------------------------------------------
-- * Type class for conversion to/from terms
class IsTerm a where
toTerm :: a -> Term
fromTerm :: MonadPlus m => Term -> m a
instance IsTerm Term where
toTerm = id
fromTerm = return
instance IsTerm ShowString where
toTerm = Var . fromShowString
fromTerm (Var s) = return (ShowString s)
fromTerm _ = fail "fromTerm"
instance (IsTerm a, IsTerm b) => IsTerm (Either a b) where
toTerm = either toTerm toTerm
fromTerm expr =
liftM Left (fromTerm expr) `mplus`
liftM Right (fromTerm expr)
fromTermM :: (Monad m, IsTerm a) => Term -> m a
fromTermM = maybe (fail "fromTermM") return . fromTerm
fromTermWith :: (Monad m, IsTerm a) => (Symbol -> [a] -> m a) -> Term -> m a
fromTermWith f a =
case getSpine a of
(t, xs) -> isCon t >>= \s -> mapM fromTermM xs >>= f s
-----------------------------------------------------------
-- * Utility functions
getSpine :: Term -> (Term, [Term])
getSpine = rec []
where
rec xs (App f a) = rec (a:xs) f
rec xs a = (a, xs)
getConSpine :: Monad m => Term -> m (Symbol, [Term])
getConSpine a = liftM (\s -> (s, xs)) (isCon b)
where (b, xs) = getSpine a
makeTerm :: Term -> [Term] -> Term
makeTerm = foldl App
makeConTerm :: Symbol -> [Term] -> Term
makeConTerm = makeTerm . Con
unary :: Symbol -> Term -> Term
unary = App . Con
binary :: Symbol -> Term -> Term -> Term
binary s = App . App (Con s)
isUnary :: Symbol -> Term -> Maybe Term
isUnary s term =
case getSpine term of
(t, [a]) | isCon t == Just s -> Just a
_ -> Nothing
isBinary :: Symbol -> Term -> Maybe (Term, Term)
isBinary s term =
case getSpine term of
(t, [a, b]) | isCon t == Just s -> Just (a, b)
_ -> Nothing
isVar :: Monad m => Term -> m String
isVar (Var s) = return s
isVar _ = fail "isVar"
isCon :: Monad m => Term -> m Symbol
isCon (Con s) = return s
isCon _ = fail "isCon"