packages feed

ideas-0.5.8: src/Domain/Math/Expr/Conversion.hs

-----------------------------------------------------------------------------
-- Copyright 2009, 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.Conversion where

import Domain.Math.Expr.Data
import Domain.Math.Expr.Symbolic
import Domain.Math.Expr.Symbols
import Domain.Math.Data.Equation
import Domain.Math.Data.OrList
import Text.OpenMath.Object
import Common.View
import Control.Monad
import Data.Maybe
import Data.List

-----------------------------------------------------------------------
-- Type class for expressions

class IsExpr a where
   toExpr   :: a -> Expr
   fromExpr :: MonadPlus m => Expr -> m a
   exprView :: View Expr a

   -- default definitions
   toExpr   = build exprView
   fromExpr = maybe (fail "not an expression") return . match exprView
   exprView = makeView fromExpr toExpr

instance IsExpr Expr where
   exprView = identity
   
instance IsExpr a => IsExpr [a] where
   toExpr = function listSymbol . map toExpr
   fromExpr expr = isSymbol listSymbol expr >>= mapM fromExpr

instance (IsExpr a, IsExpr b) => IsExpr (Either a b) where
   toExpr = either toExpr toExpr
   fromExpr expr =
      liftM Left  (fromExpr expr) `mplus`
      liftM Right (fromExpr expr)
   
-------------------------------------------------------------
-- Conversions to the Expr data type

instance IsExpr a => IsExpr (Equation a) where
   toExpr (x :==: y) = binary eqSymbol (toExpr x) (toExpr y)
   fromExpr expr = do
      (e1, e2) <- isBinary eqSymbol expr
      liftM2 (:==:) (fromExpr e1) (fromExpr e2)
   
instance IsExpr a => IsExpr (OrList a) where
   toExpr ors = 
      case disjunctions ors of
         Just []  -> symbol falseSymbol
         Just [x] -> toExpr x
         Just xs  -> function orSymbol (map toExpr xs)
         Nothing  -> symbol trueSymbol 

   fromExpr expr = do
      xs <- isSymbol orSymbol expr
      ys <- mapM fromExpr xs
      return (orList ys)
    `mplus` do
      guard (isConst falseSymbol expr) >> return false
    `mplus` do
      guard (isConst trueSymbol  expr) >> return true
    `mplus`
      liftM return (fromExpr expr)
      
-------------------------------------------------------------
-- Symbol Conversion to/from OpenMath

toOMOBJ :: Expr -> OMOBJ
toOMOBJ (Var x) = OMV x
toOMOBJ (Nat n) = OMI n
toOMOBJ expr    =
   case getFunction expr of
      Just (s, []) -> 
         OMS s  
      Just (s, [Var x, e]) | s == lambdaSymbol -> 
         OMBIND (OMS lambdaSymbol) [x] (toOMOBJ e)
      Just (s, xs) -> 
         OMA (OMS s:map toOMOBJ xs)
      Nothing -> 
         error $ "toOMOBJ: " ++ show expr

fromOMOBJ :: OMOBJ -> Expr
fromOMOBJ omobj =
   case omobj of
      OMI n -> fromInteger n
      OMV x -> Var x
      OMS s -> symbol s
      OMA (OMS s:xs) -> function s (map fromOMOBJ xs)
      OMBIND (OMS s) [x] body ->
         binary s (Var x) (fromOMOBJ body)
      _ -> symbol $ Symbol Nothing $ show omobj