-----------------------------------------------------------------------------
-- Copyright 2019, Advise-Me project team. This file is distributed under 
-- the terms of the Apache License 2.0. For more information, see the files
-- "LICENSE.txt" and "NOTICE.txt", which are included in the distribution.
-----------------------------------------------------------------------------
-- |
-- Maintainer  :  bastiaan.heeren@ou.nl
-- Stability   :  provisional
-- Portability :  portable (depends on ghc)
--
-----------------------------------------------------------------------------

module Domain.Math.Equation.BalanceRules
   ( plusRule, minusRule, timesRule, divisionRule
   ) where

import Control.Monad
import Domain.Math.Data.Relation
import Domain.Math.Expr
import Domain.Math.Numeric.Views
import Ideas.Common.Library

factorRef, termRef :: Ref Expr
factorRef = makeRef "factor"
termRef   = makeRef "term"

plusRule :: Functor f => ParamTrans Expr (f Expr)
plusRule = parameter1 termRef $ \a -> Just . fmap (:+: a)

minusRule :: Functor f => ParamTrans Expr (f Expr)
minusRule = parameter1 termRef $ \a -> Just . fmap (:-: a)

timesRule :: Functor f => ParamTrans Expr (f Expr)
timesRule = parameter1 factorRef $ \a -> unlessZero a . fmap (a :*:)

divisionRule :: ParamTrans Expr (Equation Expr)
divisionRule = parameter1 factorRef $ \a -> unlessZero a . fmap (:/: a)

unlessZero :: Expr -> a -> Maybe a
unlessZero e a = do
   r <- matchM rationalView e
   guard (r /= 0)
   return a