ideas-0.6: src/Domain/Math/Numeric/Strategies.hs
-----------------------------------------------------------------------------
-- 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.Numeric.Strategies
( naturalStrategy, integerStrategy
, rationalStrategy, fractionStrategy
, testAll
) where
import Common.Apply
import Common.Strategy
import Common.Transformation
import Common.Uniplate
import Common.View
import Domain.Math.Expr
import Domain.Math.Numeric.Rules
import Domain.Math.Numeric.Views
import Domain.Math.Numeric.Generators
import Prelude hiding (repeat)
import Test.QuickCheck hiding (label)
------------------------------------------------------------
-- Strategies
naturalStrategy :: LabeledStrategy Expr
naturalStrategy = label "simplify" $ repeat $ alternatives $ map swRule
[ calcPlusWith "nat" natView
, calcMinusWith "nat" natView
, calcTimesWith "nat" natView
, calcDivisionWith "nat" natView
, doubleNegate
, negateZero
, plusNegateLeft
, plusNegateRight
, minusNegateLeft
, minusNegateRight
, timesNegateLeft
, timesNegateRight
, divisionNegateLeft
, divisionNegateRight
]
where
natView = makeView f fromInteger
where
f (Nat n) = Just n
f _ = Nothing
integerStrategy :: LabeledStrategy Expr
integerStrategy = label "simplify" $ repeat $ alternatives $ map swRule
[ calcPlusWith "int" integerNormalForm
, calcMinusWith "int" integerNormalForm
, calcTimesWith "int" integerNormalForm
, calcDivisionWith "int" integerNormalForm
, doubleNegate
, negateZero
]
rationalStrategy :: LabeledStrategy Expr
rationalStrategy = label "simplify" $ repeat $ alternatives $ map swRule
[ calcPlusWith "rational" rationalRelaxedForm
, calcMinusWith "rational" rationalRelaxedForm
, calcTimesWith "rational" rationalRelaxedForm
, calcDivisionWith "int" integerNormalForm
, doubleNegate
, negateZero
, divisionDenominator
, divisionNumerator
, simplerFraction
]
fractionStrategy :: LabeledStrategy Expr
fractionStrategy = label "simplify" $ repeat $ alternatives $ map swRule
[ fractionPlus, fractionPlusScale, fractionTimes
, calcPlusWith "int" integerNormalForm
, calcMinusWith "int" integerNormalForm
, calcTimesWith "int" integerNormalForm -- not needed?
, calcDivisionWith "int" integerNormalForm
, doubleNegate
, negateZero
, divisionDenominator
, divisionNumerator
, simplerFraction -- only apply when fractionPlusScale is not applicable
]
swRule :: Uniplate a => Rule a -> Rule a
swRule r = makeSimpleRuleList (name r) (somewhereM (applyAll r))
------------------------------------------------------------
-- Test code
testAll :: IO ()
testAll = sequence_ [test1, test2, test3, test4]
test1 = quickCheck $ forAll (sized integerGenerator) $ \e ->
Prelude.not (e `belongsTo` integerView) ||
applyD naturalStrategy e `belongsTo` integerNormalForm
test2 = quickCheck $ forAll (sized integerGenerator) $ \e ->
Prelude.not (e `belongsTo` integerView) ||
applyD integerStrategy e `belongsTo` integerNormalForm
test3 = quickCheck $ forAll (sized rationalGenerator) $ \e ->
Prelude.not (e `belongsTo` rationalView) ||
applyD rationalStrategy e `belongsTo` rationalNormalForm
test4 = quickCheck $ forAll (sized rationalGenerator) $ \e ->
Prelude.not (e `belongsTo` rationalView) ||
applyD fractionStrategy e `belongsTo` rationalNormalForm
{- testC = quickCheck $ forAll (sized rationalGenerator) $ \e ->
let a = cleanUp e
in a == cleanUp a -}