packages feed

ideas-0.6: src/Domain/Math/Expr/Symbolic.hs

{-# LANGUAGE TypeSynonymInstances #-}
-----------------------------------------------------------------------------
-- 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)
--
-----------------------------------------------------------------------------
module Domain.Math.Expr.Symbolic 
   ( module Domain.Math.Expr.Symbolic, Symbol
   ) where

import Control.Monad
import Data.Maybe
import Common.Rewriting.Term
import qualified Text.OpenMath.Symbol as OM

makeSymbol :: String -> String -> Symbol
makeSymbol = S . Just

class IsSymbol a where
   toSymbol   :: a -> Symbol
   fromSymbol :: Symbol -> a

instance IsSymbol Symbol where
   toSymbol   = id
   fromSymbol = id

instance IsSymbol String where
   toSymbol = S Nothing
   fromSymbol (S (Just a) b) = a ++ "." ++ b
   fromSymbol (S Nothing  b) = b

instance IsSymbol OM.Symbol where
   toSymbol s = S (OM.dictionary s) (OM.symbolName s) 
   fromSymbol (S (Just a) b) = OM.makeSymbol a b
   fromSymbol (S Nothing  b) = OM.extraSymbol b

stringToSymbol :: String -> Symbol
stringToSymbol s = 
   case break (=='.') s of
      (xs, _:ys) -> S (Just xs) ys
      _          -> S Nothing s

-------------------------------------------------------------------
-- Type class for symbolic representations

class Symbolic a where
   -- constructing
   variable   :: String -> a
   symbol     :: Symbol -> a
   function   :: Symbol -> [a] -> a
   -- matching
   getVariable :: MonadPlus m => a -> m String
   getSymbol   :: MonadPlus m => a -> m Symbol
   getFunction :: MonadPlus m => a -> m (Symbol, [a])
   isSymbol    :: MonadPlus m => Symbol -> a -> m [a]
   -- default definition
   symbol s = function s []
   getSymbol a = do
      (t, as) <- getFunction a 
      guard (null as)
      return t
   isSymbol s a = do
      (t, as) <- getFunction a
      guard (s==t)
      return as
   
instance Symbolic Term where 
   variable    = Var
   symbol      = Con
   function    = makeConTerm
   getVariable = isVar
   getSymbol   = isCon
   getFunction = getConSpine
   
nullary :: (IsSymbol s, Symbolic a) => s -> a
nullary = symbol . toSymbol
   
unary :: (IsSymbol s, Symbolic a) => s -> a -> a
unary f a = function (toSymbol f) [a]

binary :: (IsSymbol s, Symbolic a) => s -> a -> a -> a
binary f a b = function (toSymbol f) [a, b]

isConst :: (IsSymbol s, Symbolic a) => s -> a -> Bool
isConst s = maybe False null . isSymbol (toSymbol s) 

isVariable :: Symbolic a => a -> Bool
isVariable = isJust . getVariable

isUnary :: (IsSymbol s, Symbolic a, MonadPlus m) => s -> a -> m a
isUnary s a = 
   case isSymbol (toSymbol s) a of
      Just [x] -> return x
      _ -> mzero

isBinary :: (IsSymbol s, Symbolic a, MonadPlus m) => s -> a -> m (a, a)
isBinary s a = 
   case isSymbol (toSymbol s) a of
      Just [x, y] -> return (x, y)
      _ -> mzero

-- left-associative by default
isAssoBinary :: (IsSymbol s, Symbolic a, MonadPlus m) => s -> a -> m (a, a)
isAssoBinary s a =
   case isSymbol (toSymbol s) a of
      Just [x, y] -> return (x, y)
      Just (x:xs) | length xs > 1 -> return (x, function (toSymbol s) xs)
      _ -> mzero
      
fromTermWith :: (MonadPlus m, IsSymbol s, IsTerm a) 
             => (s -> [a] -> m a) -> Term -> m a
fromTermWith f term = do
   (s, xs) <- getFunction term
   ys <- mapM fromTermM xs
   f (fromSymbol s) ys