tasty-laws-0.3: Test/Tasty/Laws/Monad.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ScopedTypeVariables #-}
-- | This module is intended to be imported @qualified@, for example:
--
-- > import qualified Test.Tasty.Laws.Monad as Monad
--
module Test.Tasty.Laws.Monad
( test
, testMono
, testMonoExhaustive
) where
#if !MIN_VERSION_base(4,8,0)
import Control.Applicative (Applicative)
#endif
import Data.Functor.Identity (Identity)
import Test.SmallCheck.Series (Series, Serial(series))
import Test.SmallCheck.Laws.Monad (associativity, associativitySum)
import Test.Tasty (TestTree, testGroup)
import Test.Tasty.SmallCheck (testProperty)
import qualified Test.Tasty.Laws.Applicative as Applicative
-- | @tasty@ 'TestTree' for 'Monad' laws. The type signature forces the
-- parameter to be '()' which, unless you are dealing with non-total
-- functions, should be enough to test any 'Monad's.
test
:: ( Applicative m, Monad m
, Eq (m ()), Eq (m (m ()))
, Show (m ()), Show (m (() -> ()))
, Serial Identity (m ())
, Serial IO (m ()), Serial IO (m (() -> ()))
)
=> Series IO (m ()) -> TestTree
test = testMonoExhaustive
-- | @tasty@ 'TestTree' for 'Monad' laws. Monomorphic sum 'Series'.
testMono
:: forall m a .
( Applicative m, Monad m
, Eq a, Eq (m a), Eq (m (m a))
, Show a, Show (m a), Show (m (a -> a))
, Serial Identity a, Serial Identity (m a)
, Serial IO a, Serial IO (a -> a)
, Serial IO (m a) ,Serial IO (m (a -> a)), Serial IO (a -> m a)
)
=> Series IO (m a) -> TestTree
testMono ms = testGroup "Monad laws"
[ Applicative.testMono ms
, testProperty "(m >>= f) >>= g ≡ m (f >=> g)"
$ associativitySum ms (series :: Series IO (a -> m a))
(series :: Series IO (a -> m a))
]
-- | @tasty@ 'TestTree' for 'Monad' laws. Monomorphic product 'Series'.
testMonoExhaustive
:: forall m a .
( Applicative m, Monad m
, Eq a, Eq (m a), Eq (m (m a))
, Show a, Show (m a), Show (m (a -> a))
, Serial Identity a, Serial Identity (m a)
, Serial IO a, Serial IO (a -> a)
, Serial IO (m a) ,Serial IO (m (a -> a)), Serial IO (a -> m a)
)
=> Series IO (m a) -> TestTree
testMonoExhaustive ms = testGroup "Monad laws"
[ Applicative.testMono ms
, testProperty "(m >>= f) >>= g ≡ m (f >=> g)"
$ associativity ms (series :: Series IO (a -> m a))
(series :: Series IO (a -> m a))
]