quickcheck-classes 0.4.13 → 0.4.14
raw patch · 10 files changed
+232/−15 lines, 10 filesdep ~semirings
Dependency ranges changed: semirings
Files
- changelog.md +15/−0
- quickcheck-classes.cabal +5/−3
- src/Test/QuickCheck/Classes.hs +39/−4
- src/Test/QuickCheck/Classes/Alternative.hs +9/−4
- src/Test/QuickCheck/Classes/Applicative.hs +1/−1
- src/Test/QuickCheck/Classes/Category.hs +2/−2
- src/Test/QuickCheck/Classes/MonadZip.hs +1/−1
- src/Test/QuickCheck/Classes/Plus.hs +75/−0
- src/Test/QuickCheck/Classes/Semigroup.hs +18/−0
- src/Test/QuickCheck/Classes/Semigroupoid.hs +67/−0
changelog.md view
@@ -4,9 +4,24 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to the [Haskell Package Versioning Policy](https://pvp.haskell.org/). +## [0.4.14] - 2018-07-23+### Added+- commutativeSemigroupLaws+- the following typeclasses:+ `Data.Semigroupoid.Semigroupoid` (semigroupoids)+ `Data.Functor.Plus.Plus` (semigroupoids)++### Change+- semiringLaws were never exported, we now export them.+- make documentation for `MonadPlus` and `Alternative` consistent.+- bump semirings to 0.2.0.0+- deprecate `Test.QuickCheck.Classes.specialisedLawsCheckMany`+ in favour of `Test.QuickCheck.Classes.lawsCheckOne`+ ## [0.4.13] - 2018-07-18 ### Added - Laws for `Enum` typeclass.+- Laws for `Category` typeclass. ## [0.4.12] - 2018-06-07 ### Added
quickcheck-classes.cabal view
@@ -1,5 +1,5 @@ name: quickcheck-classes-version: 0.4.13+version: 0.4.14 synopsis: QuickCheck common typeclasses description: This library provides QuickCheck properties to ensure@@ -11,7 +11,7 @@ homepage: https://github.com/andrewthad/quickcheck-classes#readme license: BSD3 license-file: LICENSE-author: Andrew Martin, Daniel Cartwright+author: Andrew Martin, chessai maintainer: andrew.thaddeus@gmail.com copyright: 2018 Andrew Martin category: Testing@@ -72,8 +72,10 @@ Test.QuickCheck.Classes.MonadZip Test.QuickCheck.Classes.Monoid Test.QuickCheck.Classes.Ord+ Test.QuickCheck.Classes.Plus Test.QuickCheck.Classes.Prim Test.QuickCheck.Classes.Semigroup+ Test.QuickCheck.Classes.Semigroupoid Test.QuickCheck.Classes.Semiring Test.QuickCheck.Classes.ShowRead Test.QuickCheck.Classes.Storable@@ -92,7 +94,7 @@ if flag(semigroupoids) build-depends: semigroupoids if flag(semirings)- build-depends: semirings >= 0.1.3+ build-depends: semirings >= 0.2.0.0 default-language: Haskell2010 test-suite test
src/Test/QuickCheck/Classes.hs view
@@ -10,13 +10,13 @@ ( -- * Running lawsCheck , lawsCheckMany- , specialisedLawsCheckMany + , lawsCheckOne+ , specialisedLawsCheckMany -- * Properties -- ** Ground types #if MIN_VERSION_base(4,7,0) , bitsLaws #endif- , commutativeMonoidLaws , eqLaws , integralLaws #if MIN_VERSION_base(4,7,0)@@ -26,11 +26,16 @@ , jsonLaws #endif , monoidLaws+ , commutativeMonoidLaws , ordLaws , enumLaws , boundedEnumLaws , primLaws , semigroupLaws+ , commutativeSemigroupLaws+#if defined(VERSION_semirings)+ , semiringLaws+#endif , showReadLaws , storableLaws #if MIN_VERSION_QuickCheck(2,10,0) && (MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,4,0))@@ -42,13 +47,23 @@ #endif , applicativeLaws #if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,5,0)- , bifunctorLaws + , bifunctorLaws+ , categoryLaws+ , commutativeCategoryLaws #endif , foldableLaws , functorLaws , monadLaws , monadPlusLaws , monadZipLaws+#if defined(VERSION_semigroupoids)+ , plusLaws+ , extendedPlusLaws+#endif+#if defined(VERSION_semigroupoids) && MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,5,0)+ , semigroupoidLaws+ , commutativeSemigroupoidLaws+#endif , traversableLaws #endif -- * Types@@ -76,6 +91,9 @@ import Test.QuickCheck.Classes.Ord import Test.QuickCheck.Classes.Prim import Test.QuickCheck.Classes.Semigroup+#if defined(VERSION_semirings)+import Test.QuickCheck.Classes.Semiring+#endif import Test.QuickCheck.Classes.ShowRead import Test.QuickCheck.Classes.Storable @@ -92,11 +110,18 @@ #if MIN_VERSION_transformers(0,5,0) import Test.QuickCheck.Classes.Bifunctor #endif+#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,4,0)+import Test.QuickCheck.Classes.Category+#endif import Test.QuickCheck.Classes.Foldable import Test.QuickCheck.Classes.Functor import Test.QuickCheck.Classes.Monad import Test.QuickCheck.Classes.MonadPlus import Test.QuickCheck.Classes.MonadZip+#if defined(VERSION_semigroupoids) && MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,4,0)+import Test.QuickCheck.Classes.Plus+import Test.QuickCheck.Classes.Semigroupoid+#endif import Test.QuickCheck.Classes.Traversable #endif #endif@@ -138,9 +163,20 @@ -- ToJSON/FromJSON: Encoding Equals Value +++ OK, passed 100 tests. -- ToJSON/FromJSON: Partial Isomorphism +++ OK, passed 100 tests. -- Show/Read: Partial Isomorphism +++ OK, passed 100 tests.+{-# DEPRECATED specialisedLawsCheckMany "Use the better-named 'Test.QuickCheck.Classes.lawsCheckOne' instead" #-} specialisedLawsCheckMany :: Proxy a -> [Proxy a -> Laws] -> IO () specialisedLawsCheckMany p ls = foldlMapM (lawsCheck . ($ p)) ls +-- | A convenience function that allows one to check many typeclass+-- instances of the same type.+--+-- >>> specialisedLawsCheckMany (Proxy :: Proxy Word) [jsonLaws, showReadLaws]+-- ToJSON/FromJSON: Encoding Equals Value +++ OK, passed 100 tests.+-- ToJSON/FromJSON: Partial Isomorphism +++ OK, passed 100 tests.+-- Show/Read: Partial Isomorphism +++ OK, passed 100 tests.+lawsCheckOne :: Proxy a -> [Proxy a -> Laws] -> IO ()+lawsCheckOne p ls = foldlMapM (lawsCheck . ($ p)) ls+ -- | A convenience function for checking multiple typeclass instances -- of multiple types. Consider the following Haskell source file: --@@ -240,4 +276,3 @@ -- instance for IO on older GHCs. foldlMapM :: (Foldable t, Monoid b, Monad m) => (a -> m b) -> t a -> m b foldlMapM f = foldlM (\b a -> liftM (mappend b) (f a)) mempty-
src/Test/QuickCheck/Classes/Alternative.hs view
@@ -28,19 +28,24 @@ -- | Tests the following alternative properties: ----- [/Identity/]+-- [/Left Identity/] -- @'empty' '<|>' x ≡ x@+-- [/Right Identity/] -- @x '<|>' 'empty' ≡ x@ -- [/Associativity/] -- @a '<|>' (b '<|>' c) ≡ (a '<|>' b) '<|>' c)@ alternativeLaws :: (Alternative f, Eq1 f, Show1 f, Arbitrary1 f) => proxy f -> Laws alternativeLaws p = Laws "Alternative"- [ ("Identity", alternativeIdentity p)+ [ ("Left Identity", alternativeLeftIdentity p)+ , ("Right Identity", alternativeRightIdentity p) , ("Associativity", alternativeAssociativity p) ] -alternativeIdentity :: forall proxy f. (Alternative f, Eq1 f, Show1 f, Arbitrary1 f) => proxy f -> Property-alternativeIdentity _ = property $ \(Apply (a :: f Integer)) -> (eq1 (empty <|> a) a) && (eq1 a (empty <|> a))+alternativeLeftIdentity :: forall proxy f. (Alternative f, Eq1 f, Show1 f, Arbitrary1 f) => proxy f -> Property+alternativeLeftIdentity _ = property $ \(Apply (a :: f Integer)) -> (eq1 (empty <|> a) a)++alternativeRightIdentity :: forall proxy f. (Alternative f, Eq1 f, Show1 f, Arbitrary1 f) => proxy f -> Property+alternativeRightIdentity _ = property $ \(Apply (a :: f Integer)) -> (eq1 a (empty <|> a)) alternativeAssociativity :: forall proxy f. (Alternative f, Eq1 f, Show1 f, Arbitrary1 f) => proxy f -> Property alternativeAssociativity _ = property $ \(Apply (a :: f Integer)) (Apply (b :: f Integer)) (Apply (c :: f Integer)) -> eq1 (a <|> (b <|> c)) ((a <|> b) <|> c)
src/Test/QuickCheck/Classes/Applicative.hs view
@@ -31,7 +31,7 @@ -- [/Identity/] -- @'pure' 'id' '<*>' v ≡ v@ -- [/Composition/]--- @'pure' (.) '<*>' u '<*>' v '<*>' w ≡ u '<*>' (v '<*>' w)@+-- @'pure' ('.') '<*>' u '<*>' v '<*>' w ≡ u '<*>' (v '<*>' w)@ -- [/Homomorphism/] -- @'pure' f '<*>' 'pure' x ≡ 'pure' (f x)@ -- [/Interchange/]
src/Test/QuickCheck/Classes/Category.hs view
@@ -28,7 +28,7 @@ -- | Tests the following 'Category' properties: -- -- [/Right Identity/]--- @f '.' 'id' ≡ f+-- @f '.' 'id' ≡ f@ -- [/Left Identity/] -- @'id' '.' f ≡ f@ -- [/Associativity/]@@ -40,7 +40,7 @@ categoryLaws p = Laws "Category" [ ("Right Identity", categoryRightIdentity p) , ("Left Identity", categoryLeftIdentity p)- , ("Second Identity", categoryAssociativity p)+ , ("Associativity", categoryAssociativity p) ] -- | Test everything from 'categoryLaws' plus the following:
src/Test/QuickCheck/Classes/MonadZip.hs view
@@ -11,7 +11,7 @@ ) where import Control.Applicative-import Control.Arrow ((***))+import Control.Arrow (Arrow(..)) import Control.Monad.Zip (MonadZip(mzip)) import Test.QuickCheck hiding ((.&.)) #if MIN_VERSION_QuickCheck(2,10,0)
+ src/Test/QuickCheck/Classes/Plus.hs view
@@ -0,0 +1,75 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ScopedTypeVariables #-}++{-# OPTIONS_GHC -Wall #-}++module Test.QuickCheck.Classes.Plus+ (+#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,4,0)+#if defined(VERSION_semigroupoids)+ plusLaws+ , extendedPlusLaws+#endif+#endif+ ) where++import Data.Functor++#if defined(VERSION_semigroupoids)+import Data.Functor.Alt (Alt)+import Data.Functor.Plus (Plus)+import qualified Data.Functor.Alt as Alt+import qualified Data.Functor.Plus as Plus+#endif++import Test.QuickCheck hiding ((.&.))+#if MIN_VERSION_QuickCheck(2,10,0)+import Test.QuickCheck.Arbitrary (Arbitrary1(..))+#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,4,0)+import Data.Functor.Classes+import qualified Control.Applicative as Alternative+#endif+#endif+import Test.QuickCheck.Property (Property)++import Test.QuickCheck.Classes.Common++#if MIN_VERSION_QuickCheck(2,10,0)++#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,4,0)++-- | Tests the following alt properties:+--+-- [/Left Identity/]+-- @'Plus.zero' 'Alt.<!>' m ≡ m@+-- [/Right Identity/]+-- @m 'Alt.<!>' 'Plus.zero' ≡ m@+#if defined(VERSION_semigroupoids)+plusLaws :: (Plus f, Eq1 f, Show1 f, Arbitrary1 f) => proxy f -> Laws+plusLaws p = Laws "Plus"+ [ ("Left Identity", plusLeftIdentity p)+ , ("Right Identity", plusRightIdentity p)+ ]++-- | Tests everything from 'altLaws', plus the following:+--+-- [/Congruency/]+-- @'Plus.zero' ≡ 'Alternative.empty'@+extendedPlusLaws :: (Plus f, Alternative.Alternative f, Eq1 f, Show1 f, Arbitrary1 f) => proxy f -> Laws+extendedPlusLaws p = Laws "Plus extended to Alternative" $ lawsProperties (plusLaws p) +++ [ ("Congruency", extendedPlusLaw p)+ ]++extendedPlusLaw :: forall proxy f. (Plus f, Alternative.Alternative f, Eq1 f, Show1 f, Arbitrary1 f) => proxy f -> Property+extendedPlusLaw _ = property $ eq1 (Plus.zero :: f Integer) (Alternative.empty :: f Integer)++plusLeftIdentity :: forall proxy f. (Plus f, Eq1 f, Show1 f, Arbitrary1 f) => proxy f -> Property+plusLeftIdentity _ = property $ \(Apply (m :: f Integer)) -> eq1 (Plus.zero Alt.<!> m) m++plusRightIdentity :: forall proxy f. (Plus f, Eq1 f, Show1 f, Arbitrary1 f) => proxy f -> Property+plusRightIdentity _ = property $ \(Apply (m :: f Integer)) -> eq1 (m Alt.<!> Plus.zero) m++#endif+#endif+#endif+
src/Test/QuickCheck/Classes/Semigroup.hs view
@@ -4,6 +4,7 @@ module Test.QuickCheck.Classes.Semigroup ( semigroupLaws+ , commutativeSemigroupLaws ) where import Prelude hiding (foldr1)@@ -32,6 +33,15 @@ , ("Times", semigroupTimes p) ] +-- | Tests everything from 'semigroupLaws', plus the following:+--+-- [/Commutative/]+-- @a '<>' b ≡ b '<>' a@+commutativeSemigroupLaws :: (Semigroup a, Eq a, Arbitrary a, Show a) => Proxy a -> Laws+commutativeSemigroupLaws p = Laws "Commutative Semigroup" $ lawsProperties (semigroupLaws p) +++ [ ("Commutative", semigroupCommutative p)+ ]+ semigroupAssociative :: forall a. (Semigroup a, Eq a, Arbitrary a, Show a) => Proxy a -> Property semigroupAssociative _ = myForAllShrink True (const True) (\(a :: a,b,c) -> ["a = " ++ show a, "b = " ++ show b, "c = " ++ show c])@@ -39,6 +49,14 @@ (\(a,b,c) -> a <> (b <> c)) "(a <> b) <> c" (\(a,b,c) -> (a <> b) <> c)++semigroupCommutative :: forall a. (Semigroup a, Eq a, Arbitrary a, Show a) => Proxy a -> Property+semigroupCommutative _ = myForAllShrink True (const True)+ (\(a :: a,b) -> ["a = " ++ show a, "b = " ++ show b])+ "a <> b"+ (\(a,b) -> a <> b)+ "b <> a"+ (\(a,b) -> b <> a) semigroupConcatenation :: forall a. (Semigroup a, Eq a, Arbitrary a, Show a) => Proxy a -> Property semigroupConcatenation _ = myForAllShrink True (const True)
+ src/Test/QuickCheck/Classes/Semigroupoid.hs view
@@ -0,0 +1,67 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ScopedTypeVariables #-}++{-# OPTIONS_GHC -Wall #-}++module Test.QuickCheck.Classes.Semigroupoid+ (+#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,5,0)+#if defined(VERSION_semigroupoids)+ semigroupoidLaws+ , commutativeSemigroupoidLaws+#endif+#endif + ) where++import Prelude hiding (id, (.))+#if defined(VERSION_semigroupoids)+import Data.Semigroupoid (Semigroupoid(..))+#endif+import Test.QuickCheck hiding ((.&.))+#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,4,0)+import Data.Functor.Classes+#endif+import Test.QuickCheck.Property (Property)++import Test.QuickCheck.Classes.Common++#if MIN_VERSION_QuickCheck(2,10,0)++#if MIN_VERSION_base(4,9,0) || MIN_VERSION_transformers(0,5,0)++#if defined (VERSION_semigroupoids)+-- | Tests the following 'Semigroupoid' properties:+--+-- [/Associativity/]+-- @f `'o'` (g `'o'` h) ≡ (f `'o'` g) `'o'` h@+--+-- /Note/: This property test is only available when this package is built with+-- @base-4.9+@ or @transformers-0.5+@.+semigroupoidLaws :: (Semigroupoid sem, Eq2 sem, Show2 sem, Arbitrary2 sem) => proxy sem -> Laws+semigroupoidLaws p = Laws "Semigroupoid"+ [ ("Associativity", semigroupoidAssociativity p)+ ]++-- | Tests everything from 'semigroupoidLaws' plus the following:+--+-- [/Commutative/]+-- @f `'o'` g ≡ g `'o'` f@+--+-- /Note/: This property test is only available when this package is built with+-- @base-4.9+@ or @transformers-0.5+@.+commutativeSemigroupoidLaws :: (Semigroupoid sem, Eq2 sem, Show2 sem, Arbitrary2 sem) => proxy sem -> Laws+commutativeSemigroupoidLaws p = Laws "Commutative Semigroupoid" $ lawsProperties (semigroupoidLaws p) +++ [ ("Commutative", semigroupoidCommutativity p)+ ]++semigroupoidAssociativity :: forall proxy sem. (Semigroupoid sem, Eq2 sem, Show2 sem, Arbitrary2 sem) => proxy sem -> Property+semigroupoidAssociativity _ = property $ \(Apply2 (f :: sem Integer Integer)) (Apply2 (g :: sem Integer Integer)) (Apply2 (h :: sem Integer Integer)) -> eq2 (f `o` (g `o` h)) ((f `o` g) `o` h)++semigroupoidCommutativity :: forall proxy sem. (Semigroupoid sem, Eq2 sem, Show2 sem, Arbitrary2 sem) => proxy sem -> Property+semigroupoidCommutativity _ = property $ \(Apply2 (f :: sem Integer Integer)) (Apply2 (g :: sem Integer Integer)) -> eq2 (f `o` g) (g `o` f)++#endif++#endif++#endif