polynom-0.1.0.0: test.hs
{-# LANGUAGE StandaloneDeriving, GeneralizedNewtypeDeriving, DeriveFunctor, DeriveTraversable, UndecidableInstances #-}
import Prelude (IO, Integer, Show, toEnum, fromEnum, enumFromTo)
import Control.Applicative
import Control.Category
import Control.Category.Unicode
import Control.Monad
import Control.Monad.Trans.Class
import Data.Bool
import Data.CList
import Data.Eq
import Data.Foldable hiding (sum)
import Data.Function (($), flip)
import qualified Data.List as List
import Data.Monoid
import Data.Ord
import Data.Traversable
import Numeric.Algebra
import Numeric.Decidable.Zero
import Test.SmallCheck.Series
import Test.Tasty
import Test.Tasty.SmallCheck
import Data.Polynom.Impl
import Data.Polynom.Show ()
instance (Serial m α, Serial m a, Ord α, Abelian a, DecidableZero a) => Serial m (Polynom α a) where
series = series >>- \ (ListSet αs) ->
fromList ∘ List.zip αs <$>
mapS id (series <$ αs) `suchThat` foldl (pure (not ∘ isZero)) True
where mapS f = List.foldr (\ x ys -> (:) <$> f x <~> ys) (pure [])
suchThat :: Monad m => Series m a -> (a -> Bool) -> Series m a
suchThat s p = s >>= liftA2 (bool empty) pure p
newtype ListSet a = ListSet [a] deriving (Show)
instance (Serial m a) => Serial m (ListSet a) where
series = getDepth >>= lift ∘ flip listM series >>=
foldr ((<|>) ∘ pure ∘ ListSet) empty ∘ List.inits
instance Monad m => Serial m Natural where
series = generate $ flip List.take [0..]
newtype Monom n a = Monom (CList n a) deriving (Functor, Foldable, Traversable, Eq, Ord, Show)
deriving instance Applicative (CList n) => Applicative (Monom n)
instance Monad m => Serial m (Monom Zero Natural) where
series = pure (Monom Nil)
instance (Monad m, Serial m (Monom n Natural)) => Serial m (Monom (Succ n) Natural) where
series = enumFromTo 0 ∘ toEnum <$> getDepth >>-
foldr (\/) empty ∘ fmap (\ k ->
(\ (Monom ks) -> Monom (k:.ks)) <$>
localDepth (+ negate (fromEnum k)) series)
instance (Applicative (CList n), Monoidal a) => Monoid (Monom n a) where
mempty = Monom (pure zero)
Monom αs `mappend` Monom βs = Monom (liftA2 (+) αs βs)
main :: IO ()
main = defaultMain $
testGroup "root"
[testProperty "Distributivity" $ \ p q r ->
isZero (p*r + q*r - (p + q)*r :: P2 Integer),
testGroup "Differentiation"
[testProperty "Linearity" $ \ α p q ->
isZero (formalDiff α p + formalDiff α q - formalDiff α (p + q) :: P2 Integer),
testProperty "Product Rule" $ \ p q ->
flip all (Monom <$> [1:.0:.Nil, 0:.1:.Nil]) $ \ α ->
isZero (formalDiff α (p*q) - formalDiff α p*q - p*formalDiff α q :: P2 Integer)]]
type P2 = Polynom (Monom (Succ (Succ Zero)) Natural)