packages feed

tasty-quickcheck-laws 0.0.2 → 0.0.3

raw patch · 8 files changed

+272/−7 lines, 8 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Test.Tasty.QuickCheck.Laws.IdentityMonad: testIdentityMonadLawBind :: (Monad m, Eq b, Show t, CoArbitrary a, Arbitrary (m b), Arbitrary t, Arbitrary (m a), Show (m a)) => Proxy m -> Proxy t -> Proxy a -> Proxy b -> (forall u. Eq u => t -> m u -> m u -> Bool) -> (forall a. m a -> a) -> TestTree
+ Test.Tasty.QuickCheck.Laws.IdentityMonad: testIdentityMonadLawReturnUnwrap :: (Monad m, Eq a, Show t, Arbitrary t, Arbitrary (m a), Show (m a)) => Proxy m -> Proxy t -> Proxy a -> (forall u. Eq u => t -> m u -> m u -> Bool) -> (forall a. m a -> a) -> TestTree
+ Test.Tasty.QuickCheck.Laws.IdentityMonad: testIdentityMonadLawUnwrapReturn :: (Monad m, Eq a, Show a, Show t, Arbitrary t, Arbitrary a, Show (m a)) => Proxy m -> Proxy t -> Proxy a -> (forall a. m a -> a) -> TestTree
+ Test.Tasty.QuickCheck.Laws.IdentityMonad: testIdentityMonadLaws :: (Monad m, Eq a, Eq b, Show t, Show a, Show (m a), Arbitrary t, Arbitrary a, CoArbitrary a, Arbitrary (m a), Arbitrary (m b), Typeable m, Typeable a) => Proxy m -> Proxy t -> Proxy a -> Proxy b -> (forall u. Eq u => t -> m u -> m u -> Bool) -> (forall a. m a -> a) -> TestTree
+ Test.Tasty.QuickCheck.Laws.Semigroup: testSemigroupLawAssociative :: (Semigroup a, Eq a, Show a, Arbitrary a) => Proxy a -> TestTree
+ Test.Tasty.QuickCheck.Laws.Semigroup: testSemigroupLaws :: (Semigroup a, Eq a, Show a, Arbitrary a, Typeable a) => Proxy a -> TestTree

Files

CHANGELOG.md view
@@ -1,6 +1,13 @@ Changelog for tasty-quickcheck-laws =================================== +0.0.3+-----++* Added+    * Identity monad laws+    * Semigroup laws+ 0.0.2 ----- 
README.md view
@@ -8,10 +8,12 @@ Currently includes laws for the following type classes:  * Eq+* Semigroup * Monoid * Functor * Applicative * Monad+* Identity Monad * State Monad * Reader Monad * Writer Monad
src/Test/Tasty/QuickCheck/Laws.hs view
@@ -16,10 +16,12 @@   , module Test.Tasty.QuickCheck.Laws.Functor   , module Test.Tasty.QuickCheck.Laws.Monad   , module Test.Tasty.QuickCheck.Laws.Monoid+  , module Test.Tasty.QuickCheck.Laws.Semigroup   , module Test.Tasty.QuickCheck.Laws.ReaderMonad   , module Test.Tasty.QuickCheck.Laws.StateMonad   , module Test.Tasty.QuickCheck.Laws.WriterMonad   , module Test.Tasty.QuickCheck.Laws.MaybeMonad+  , module Test.Tasty.QuickCheck.Laws.IdentityMonad ) where  import Test.Tasty.QuickCheck.Laws.Applicative@@ -29,7 +31,9 @@ import Test.Tasty.QuickCheck.Laws.Functor import Test.Tasty.QuickCheck.Laws.Monad import Test.Tasty.QuickCheck.Laws.Monoid+import Test.Tasty.QuickCheck.Laws.Semigroup import Test.Tasty.QuickCheck.Laws.ReaderMonad import Test.Tasty.QuickCheck.Laws.StateMonad import Test.Tasty.QuickCheck.Laws.WriterMonad import Test.Tasty.QuickCheck.Laws.MaybeMonad+import Test.Tasty.QuickCheck.Laws.IdentityMonad
+ src/Test/Tasty/QuickCheck/Laws/IdentityMonad.hs view
@@ -0,0 +1,144 @@+{- |+Module      : Test.Tasty.QuickCheck.Laws.IdentityMonad+Description : Prefab tasty trees of quickcheck properties for the identity monad laws+Copyright   : 2019, Automattic, Inc.+License     : BSD3+Maintainer  : Nathan Bloomfield (nbloomf@gmail.com)+Stability   : experimental+Portability : POSIX+-}++++{-# LANGUAGE Rank2Types #-}+module Test.Tasty.QuickCheck.Laws.IdentityMonad (+    testIdentityMonadLaws++  -- * Identity Monad Laws+  , testIdentityMonadLawUnwrapReturn+  , testIdentityMonadLawReturnUnwrap+  , testIdentityMonadLawBind+) where++import Data.Proxy+  ( Proxy(..) )+import Data.Typeable+  ( Typeable, typeRep )+import Test.Tasty+  ( TestTree, testGroup )+import Test.Tasty.QuickCheck+  ( testProperty, Property, Arbitrary(..), CoArbitrary(..) )+import Text.Show.Functions+  ()++import Test.Tasty.QuickCheck.Laws.Class++++-- | Constructs a @TestTree@ checking that the identity monad laws hold for @m@ with value types @a@ and @b@, using a given equality test for values of type @forall u. m u@. The equality context type @t@ is for constructors @m@ from which we can only extract a value within a context, such as reader-like constructors.+testIdentityMonadLaws+  :: ( Monad m+     , Eq a, Eq b+     , Show t, Show a+     , Show (m a)+     , Arbitrary t, Arbitrary a, CoArbitrary a+     , Arbitrary (m a), Arbitrary (m b)+     , Typeable m, Typeable a+     )+  => Proxy m -- ^ Type constructor under test+  -> Proxy t -- ^ Equality context for @m@+  -> Proxy a -- ^ Value type+  -> Proxy b -- ^ Value type+  -> (forall u. (Eq u) => t -> m u -> m u -> Bool) -- ^ Equality test+  -> (forall a. m a -> a) -- ^ @unwrap@+  -> TestTree+testIdentityMonadLaws pm pt pa pb eq unwrap =+  let+    label = "Identity Monad Laws for " ++ (show $ typeRep pm) ++ " with " +++      "a :: " ++ (show $ typeRep pa)+  in+    testGroup label+      [ testIdentityMonadLawUnwrapReturn pm pt pa unwrap+      , testIdentityMonadLawReturnUnwrap pm pt pa eq unwrap+      , testIdentityMonadLawBind pm pt pa pb eq unwrap+      ]++++-- | @unwrap . return === id@+testIdentityMonadLawUnwrapReturn+  :: ( Monad m, Eq a, Show a+     , Show t+     , Arbitrary t, Arbitrary a, Show (m a)+     )+  => Proxy m -- ^ Type constructor under test+  -> Proxy t -- ^ Equality context for @m@+  -> Proxy a -- ^ Value type+  -> (forall a. m a -> a) -- ^ @unwrap@+  -> TestTree+testIdentityMonadLawUnwrapReturn pm pt pa unwrap =+  testProperty "unwrap . return === id" $+    identityMonadLawUnwrapReturn pm pt pa unwrap++identityMonadLawUnwrapReturn+  :: (Monad m, Eq a)+  => Proxy m -> Proxy t -> Proxy a+  -> (forall a. m a -> a) -- ^ @unwrap@+  -> t -> a -> Bool+identityMonadLawUnwrapReturn _ _ _ unwrap t x =+  (unwrap . return $ x) == x++++-- | @unwrap . return === id@+testIdentityMonadLawReturnUnwrap+  :: ( Monad m, Eq a+     , Show t+     , Arbitrary t, Arbitrary (m a), Show (m a)+     )+  => Proxy m -- ^ Type constructor under test+  -> Proxy t -- ^ Equality context for @m@+  -> Proxy a -- ^ Value type+  -> (forall u. (Eq u) => t -> m u -> m u -> Bool) -- ^ Equality test+  -> (forall a. m a -> a) -- ^ @unwrap@+  -> TestTree+testIdentityMonadLawReturnUnwrap pm pt pa eq bail =+  testProperty "return . unwrap == id" $+    identityMonadLawReturnUnwrap pm pt pa eq bail++identityMonadLawReturnUnwrap+  :: (Monad m, Eq a)+  => Proxy m -> Proxy t -> Proxy a+  -> (forall u. (Eq u) => t -> m u -> m u -> Bool) -- ^ Equality test+  -> (forall a. m a -> a) -- ^ unwrap+  -> t -> m a -> Bool+identityMonadLawReturnUnwrap _ _ _ eq unwrap t x =+  (eq t) (return . unwrap $ x) (x)++++-- | @unwrap (x >>= f) === unwrap (f (unwrap x))@+testIdentityMonadLawBind+  :: ( Monad m, Eq b+     , Show t, CoArbitrary a, Arbitrary (m b)+     , Arbitrary t, Arbitrary (m a), Show (m a)+     )+  => Proxy m -- ^ Type constructor under test+  -> Proxy t -- ^ Equality context for @m@+  -> Proxy a -- ^ Value type+  -> Proxy b -- ^ Value type+  -> (forall u. (Eq u) => t -> m u -> m u -> Bool) -- ^ Equality test+  -> (forall a. m a -> a) -- ^ @unwrap@+  -> TestTree+testIdentityMonadLawBind pm pt pa pb eq unwrap =+  testProperty "x >>= f === f (unwrap x)" $+    identityMonadLawBind pm pt pa pb eq unwrap++identityMonadLawBind+  :: (Monad m, Eq b)+  => Proxy m -> Proxy t -> Proxy a -> Proxy b+  -> (forall u. (Eq u) => t -> m u -> m u -> Bool) -- ^ Equality test+  -> (forall a. m a -> a) -- ^ @unwrap@+  -> t -> m a -> (a -> m b) -> Bool+identityMonadLawBind _ _ _ _ eq unwrap t x f =+  (eq t) (x >>= f) (f (unwrap x))
src/Test/Tasty/QuickCheck/Laws/MaybeMonad.hs view
@@ -33,7 +33,7 @@   --- | Constructs a @TestTree@ checking that the maybe monad laws hold for @m@ with maybe type @r@ and value types @a@ and @b@, using a given equality test for values of type @forall u. m u@. The equality context type @t@ is for constructors @m@ from which we can only extract a value within a context, such as reader-like constructors.+-- | Constructs a @TestTree@ checking that the maybe monad laws hold for @m@ with value types @a@ and @b@, using a given equality test for values of type @forall u. m u@. The equality context type @t@ is for constructors @m@ from which we can only extract a value within a context, such as reader-like constructors. testMaybeMonadLaws   :: ( Monad m      , Eq a@@ -80,7 +80,7 @@   :: (Monad m, Eq a)   => Proxy m -> Proxy t -> Proxy a   -> (forall u. (Eq u) => t -> m u -> m u -> Bool) -- ^ Equality test-  -> (forall a. m a) -- ^ bail+  -> (forall a. m a) -- ^ @bail@   -> t -> m a -> Bool maybeMonadLawBailThen _ _ _ eq bail t x =   (eq t) (bail >> x) (bail)
+ src/Test/Tasty/QuickCheck/Laws/Semigroup.hs view
@@ -0,0 +1,64 @@+{- |+Module      : Test.Tasty.QuickCheck.Laws.Semigroup+Description : Prefab tasty trees of quickcheck properties for the Semigroup laws+Copyright   : 2019, Automattic, Inc.+License     : BSD3+Maintainer  : Nathan Bloomfield (nbloomf@gmail.com)+Stability   : experimental+Portability : POSIX+-}++++module Test.Tasty.QuickCheck.Laws.Semigroup (+    testSemigroupLaws++  -- * Semigroup Laws+  , testSemigroupLawAssociative+) where++import Data.Proxy+  ( Proxy(..) )+import Data.Semigroup+  ( Semigroup(..) )+import Data.Typeable+  ( Typeable, typeRep )+import Test.Tasty+  ( TestTree, testGroup )+import Test.Tasty.QuickCheck+  ( testProperty, Property, Arbitrary(..) )++import Test.Tasty.QuickCheck.Laws.Class++++-- | Constructs a @TestTree@ checking that the @Semigroup@ class laws hold for @a@.+testSemigroupLaws+  :: (Semigroup a, Eq a, Show a, Arbitrary a, Typeable a)+  => Proxy a+  -> TestTree+testSemigroupLaws pa =+  let label = "Semigroup Laws for " ++ (show $ typeRep pa) in+  testGroup label+    [ testSemigroupLawAssociative pa+    ]++++++-- | @(a <> b) <> c === a <> (b <> c)@+testSemigroupLawAssociative+  :: (Semigroup a, Eq a, Show a, Arbitrary a)+  => Proxy a+  -> TestTree+testSemigroupLawAssociative pa =+  testProperty "(a <> b) <> c === a <> (b <> c)" $+    semigroupLawAssociative pa++semigroupLawAssociative+  :: (Semigroup a, Eq a)+  => Proxy a+  -> a -> a -> a -> Bool+semigroupLawAssociative _ a b c =+  (a <> b) <> c == a <> (b <> c)
tasty-quickcheck-laws.cabal view
@@ -1,5 +1,5 @@ name:           tasty-quickcheck-laws-version:        0.0.2+version:        0.0.3 description:    Please see the README on GitHub at <https://github.com/nbloomf/tasty-quickcheck-laws#readme> homepage:       https://github.com/nbloomf/tasty-quickcheck-laws#readme bug-reports:    https://github.com/nbloomf/tasty-quickcheck-laws/issues@@ -42,10 +42,12 @@     Test.Tasty.QuickCheck.Laws.Functor     Test.Tasty.QuickCheck.Laws.Monad     Test.Tasty.QuickCheck.Laws.Monoid+    Test.Tasty.QuickCheck.Laws.Semigroup     Test.Tasty.QuickCheck.Laws.ReaderMonad     Test.Tasty.QuickCheck.Laws.StateMonad     Test.Tasty.QuickCheck.Laws.WriterMonad     Test.Tasty.QuickCheck.Laws.MaybeMonad+    Test.Tasty.QuickCheck.Laws.IdentityMonad   
test/Main.hs view
@@ -5,6 +5,7 @@ import System.Environment import Control.Monad (ap) import Test.QuickCheck+import Data.Typeable  import Test.Tasty.QuickCheck.Laws @@ -20,6 +21,11 @@       , testEqLaws pB       , testEqLaws pI       ]+    , testGroup "Semigroup Laws"+      [ testSemigroupLaws (Proxy :: Proxy [()])+      , testSemigroupLaws (Proxy :: Proxy [Bool])+      , testSemigroupLaws (Proxy :: Proxy (Maybe [()]))+      ]     , testGroup "Monoid Laws"       [ testMonoidLaws (Proxy :: Proxy [()])       , testMonoidLaws (Proxy :: Proxy [Bool])@@ -58,6 +64,11 @@       , testMonadLaws3 pEi pU pU pB pI (const (==))       , testMonadLaws3 pLs pU pU pB pI (const (==))       ]+    , testGroup "Identity Monad Laws"+      [ testIdentityMonadLaws pId pU pU pU (const (==)) unwrap+      , testIdentityMonadLaws pId pU pB pB (const (==)) unwrap+      , testIdentityMonadLaws pId pU pI pI (const (==)) unwrap+      ]     , testGroup "State Monad Laws"       [ testStateMonadLaws pSU pU pU pU stateEq get put       , testStateMonadLaws pSB pB pB pB stateEq get put@@ -116,6 +127,8 @@ pEB = Proxy :: Proxy (Error Bool) pEI = Proxy :: Proxy (Error Int) +pId = Proxy :: Proxy Identity+ pWU = Proxy :: Proxy (Writer ()) pWLs = const Proxy :: Proxy a -> Proxy (Writer [a]) @@ -127,7 +140,8 @@ -- Basic State Monad  data State s a = State-  { runState :: s -> (a,s) }+  { runState :: s -> (a,s)+  } deriving Typeable  stateEq   :: (Eq s, Eq a)@@ -162,7 +176,8 @@ -- Basic Reader Monad  data Reader r a = Reader-  { runReader :: r -> a }+  { runReader :: r -> a+  } deriving Typeable  readerEq   :: (Eq a)@@ -201,7 +216,7 @@  data Error e a = Error   { runError :: Either e a-  } deriving (Eq, Show)+  } deriving (Eq, Show, Typeable)  instance Monad (Error e) where   return a = Error (Right a)@@ -234,7 +249,7 @@  data Writer w a = Writer   { runWriter :: (a,w)-  } deriving (Eq, Show)+  } deriving (Eq, Show, Typeable)  instance (Monoid w) => Monad (Writer w) where   return a = Writer (a, mempty)@@ -275,3 +290,30 @@     ((a,f),w) = runWriter x   in     Writer (a, f w)++++-- Basic Identity Monad++data Identity a = Identity a+  deriving (Eq, Show, Typeable)++instance Functor Identity where+  fmap f (Identity x) = Identity (f x)++instance Applicative Identity where+  pure = Identity++  (Identity f) <*> (Identity x) =+    Identity (f x)++instance Monad Identity where+  return = Identity++  (Identity x) >>= f = f x++instance (Arbitrary a) => Arbitrary (Identity a) where+  arbitrary = Identity <$> arbitrary++unwrap :: Identity a -> a+unwrap (Identity x) = x