smallcheck-laws 0.2 → 0.3
raw patch · 7 files changed
+198/−19 lines, 7 files
Files
- CHANGELOG.md +9/−0
- README.md +1/−1
- Test/SmallCheck/Laws/Applicative.hs +82/−3
- Test/SmallCheck/Laws/Functor.hs +24/−1
- Test/SmallCheck/Laws/Monad.hs +42/−3
- Test/SmallCheck/Laws/Monoid.hs +35/−8
- smallcheck-laws.cabal +5/−3
CHANGELOG.md view
@@ -4,6 +4,14 @@ CHANGELOG](http://keepachangelog.com/). This project adheres to [Semantic Versioning](http://semver.org/). +## [0.3] - 2015-09-07+### Added+- *Exhaustive* property testing using `Series` product. Previous+ properties renamed appending `Sum`.++### Changed+- Rename `mconcat` `Monoid` property.+ ## [0.2] - 2015-09-04 ### Removed - Move `Tasty` modules to a separate package@@ -16,5 +24,6 @@ - Monoid Laws. - Monad laws. +[0.3]: https://github.com/jdnavarro/smallcheck-laws/compare/v0.2...v0.3 [0.2]: https://github.com/jdnavarro/smallcheck-laws/compare/v0.1...v0.2 [0.1]: https://github.com/jdnavarro/smallcheck-laws/compare/bf1caa...v0.1
README.md view
@@ -4,7 +4,7 @@ [](https://travis-ci.org/jdnavarro/smallcheck-laws) [`smallcheck`](https://hackage.haskell.org/package/smallcheck) properties for-the following laws:+testing the following laws: - Monoid - Functor
Test/SmallCheck/Laws/Applicative.hs view
@@ -6,8 +6,11 @@ -- * Applicative laws identity , composition+ , compositionSum , homomorphism+ , homomorphismSum , interchange+ , interchangeSum ) where #if !MIN_VERSION_base(4,8,0)@@ -34,6 +37,9 @@ -- @ -- '(.)' '<$>' u '<*>' v '<*>' w ≡ u '<*>' (v '<*>' w) -- @+--+-- Exhaustive generation for the 'Series' of @v@, @u@ and @w@. Be aware of+-- combinatorial explosion. composition :: ( Eq (f b) , Monad m@@ -46,14 +52,41 @@ -> Series m (f c) -> Series m (f (a -> b)) -> Property m-composition vs ws us = over (zipLogic3 vs ws us) $ \(v,w,u) ->+composition vs ws us =+ over vs $ \v ->+ over ws $ \w ->+ over us $ \u -> (pure (.) <*> u <*> v <*> w) == (u <*> (v <*> w)) +-- | Check the /composition/ law hold for the given 'Applicative' 'Series':+--+-- @+-- '(.)' '<$>' u '<*>' v '<*>' w ≡ u '<*>' (v '<*>' w)+-- @+-- This uses 'zipLogic3' for the generation 'Series' of @v@, @u@ and @w@.+compositionSum+ :: ( Eq (f b)+ , Monad m+ , Show (f c)+ , Show (f (a -> b))+ , Show (f (c -> a))+ , Applicative f+ )+ => Series m (f (c -> a))+ -> Series m (f c)+ -> Series m (f (a -> b))+ -> Property m+compositionSum vs ws us = over (zipLogic3 vs ws us) $ \(v,w,u) ->+ (pure (.) <*> u <*> v <*> w) == (u <*> (v <*> w))+ -- | Check the /homomorphism/ law hold for the given 'Applicative' 'Series': -- -- @ -- 'pure' f '<*>' 'pure' x ≡ 'pure' (f x) -- @+--+-- Exhaustive generation for the 'Series' of @x@ and @f@. Be aware of+-- combinatorial explosion. homomorphism :: forall m f a b . ( Monad m@@ -65,14 +98,40 @@ , Serial Identity b ) => Proxy f -> Series m a -> Series m (a -> b) -> Property m-homomorphism _ xs fs = over (zipLogic xs fs) $ \(x,f) ->+homomorphism _ xs fs =+ over xs $ \x ->+ over fs $ \f -> (pure f <*> (pure x :: f a)) == pure (f x) +-- | Check the /homomorphism/ law hold for the given 'Applicative' 'Series':+--+-- @+-- 'pure' f '<*>' 'pure' x ≡ 'pure' (f x)+-- @+--+-- This uses 'zipLogic' for the generation 'Series' of @x@ and @f@.+homomorphismSum+ :: forall m f a b .+ ( Monad m+ , Applicative f+ , Eq b+ , Eq (f b)+ , Show a, Show b+ , Serial Identity a+ , Serial Identity b+ )+ => Proxy f -> Series m a -> Series m (a -> b) -> Property m+homomorphismSum _ xs fs = over (zipLogic xs fs) $ \(x,f) ->+ (pure f <*> (pure x :: f a)) == pure (f x)+ -- | Check the /interchange/ law hold for the given 'Applicative' 'Series': -- -- @ -- u '<*>' 'pure' y ≡ 'pure' ($ y) '<*>' u -- @+--+-- Exhaustive generation for the 'Series' of @y@ and @u@. Be aware of+-- combinatorial explosion. interchange :: ( Eq (f b) , Monad m@@ -81,5 +140,25 @@ , Applicative f ) => Series m a -> Series m (f (a -> b)) -> Property m-interchange ys us = over (zipLogic ys us) $ \(y,u) ->+interchange ys us =+ over ys $ \y ->+ over us $ \u ->+ (u <*> pure y) == (pure ($ y) <*> u)++-- | Check the /interchange/ law hold for the given 'Applicative' 'Series':+--+-- @+-- u '<*>' 'pure' y ≡ 'pure' ($ y) '<*>' u+-- @+--+-- This uses 'zipLogic' for the generation 'Series' of @y@ and @u@.+interchangeSum+ :: ( Eq (f b)+ , Monad m+ , Show a+ , Show (f (a -> b))+ , Applicative f+ )+ => Series m a -> Series m (f (a -> b)) -> Property m+interchangeSum ys us = over (zipLogic ys us) $ \(y,u) -> (u <*> pure y) == (pure ($ y) <*> u)
Test/SmallCheck/Laws/Functor.hs view
@@ -4,6 +4,7 @@ -- * Functor laws identity , composition+ , compositionSum ) where import Data.Functor.Identity (Identity)@@ -26,11 +27,33 @@ -- @ -- 'fmap' (f . g) ≡ 'fmap' f . 'fmap' g -- @+--+-- Exhaustive generation for the @f@ and @g@ 'Series'. Be aware of+-- combinatorial explosion. composition :: ( Monad m, Functor f, Show a, Show b, Show c , Show (f a), Eq (f c) , Serial Identity a, Serial Identity b ) => Series m (f a) -> Series m (b -> c) -> Series m (a -> b) -> Property m-composition xs fs gs = over (zipLogic3 xs fs gs) $ \(x,f,g) ->+composition xs fs gs =+ over xs $ \x ->+ over fs $ \f ->+ over gs $ \g ->+ fmap (f . g) x == (fmap f . fmap g) x++-- | Check the /composition/ law hold for the given 'Functor' 'Series':+--+-- @+-- 'fmap' (f . g) ≡ 'fmap' f . 'fmap' g+-- @+--+-- This uses 'zipLogic' for the generation of the @f@ and @g@ 'Series'.+compositionSum+ :: ( Monad m, Functor f, Show a, Show b, Show c+ , Show (f a), Eq (f c)+ , Serial Identity a, Serial Identity b+ )+ => Series m (f a) -> Series m (b -> c) -> Series m (a -> b) -> Property m+compositionSum xs fs gs = over (zipLogic3 xs fs gs) $ \(x,f,g) -> fmap (f . g) x == (fmap f . fmap g) x
Test/SmallCheck/Laws/Monad.hs view
@@ -9,6 +9,7 @@ ( -- * Monad laws associativity+ , associativitySum ) where import Control.Monad ((>=>))@@ -18,6 +19,9 @@ import Test.SmallCheck.Series (Serial, Series) import Test.SmallCheck.Series.Utils (zipLogic3) ++-- This is equivalent to `(f >=> g) >=> h == f >=> (g >=> h)` which requires+-- the constraint `Eq (a -> f b)`. `Eq (f a)` is much easier to deal with. -- | Check the /associativity/ law hold for the given 'Monad' 'Series': -- -- @@@ -30,11 +34,46 @@ -- (f '>=>' g) '>=>' h == f '>=>' (g '>=>' h) -- @ ----- Assuming 'join' is the default implementation of 'Monad'.+-- Exhaustive generation of @m@, @f@ and @g@. Be aware of combinatorial+-- explosion.+--+-- This assumes 'join' derived from '>>=' from the default implementation of+-- 'Monad'.+associativity+ :: ( Monad m, Monad f+ , Show a, Show b, Show c, Show (f a), Show (f b), Show (f c)+ , Eq (f a), Eq (f c)+ , Serial Identity a, Serial Identity b, Serial Identity c+ )+ => Series m (f a)+ -> Series m (a -> f b)+ -> Series m (b -> f c)+ -> Property m+associativity ms fs gs =+ over ms $ \m ->+ over fs $ \f ->+ over gs $ \g ->+ (m >>= f >>= g) == (m >>= (f >=> g)) -- This is equivalent to `(f >=> g) >=> h == f >=> (g >=> h)` which requires -- the constraint `Eq (a -> f b)`. `Eq (f a)` is much easier to deal with.-associativity+-- | Check the /associativity/ law hold for the given 'Monad' 'Series':+--+-- @+-- (m '>>=' f) '>>=' g ≡ m (f '>=>' g)+-- @+--+-- This is equivalent to:+--+-- @+-- (f '>=>' g) '>=>' h == f '>=>' (g '>=>' h)+-- @+--+-- This uses 'zipLogic3' for the generation 'Series' of @m@, @f@ and @g@.+--+-- This assumes 'join' derived from '>>=' from the default implementation of+-- 'Monad'.+associativitySum :: ( Monad m, Monad f , Show a, Show b, Show c, Show (f a), Show (f b), Show (f c) , Eq (f a), Eq (f c)@@ -44,5 +83,5 @@ -> Series m (a -> f b) -> Series m (b -> f c) -> Property m-associativity ms fs gs = over (zipLogic3 ms fs gs) $ \(m,f,g) ->+associativitySum ms fs gs = over (zipLogic3 ms fs gs) $ \(m,f,g) -> (m >>= f >>= g) == (m >>= (f >=> g))
Test/SmallCheck/Laws/Monoid.hs view
@@ -1,11 +1,14 @@ {-# LANGUAGE CPP #-} module Test.SmallCheck.Laws.Monoid (- -- * Monoid laws+ -- * Identity leftIdentity , rightIdentity+ -- * Associativity , associativity- , mconcat+ , associativitySum+ -- * mconcat+ , mconcatProp ) where #if MIN_VERSION_base(4,8,0)@@ -20,7 +23,9 @@ import Test.SmallCheck.Series (Series) import Test.SmallCheck.Series.Utils (zipLogic3) --- | Check the /left identity/ law hold for the given 'Monoid' 'Series':+-- * Identity++-- | Check the /left identity/ law holds for the given 'Monoid' 'Series': -- -- @ -- 'mempty' '<>' x ≡ x@@ -30,7 +35,7 @@ => Series m a -> Property m leftIdentity s = over s $ \x -> mempty <> x == x --- | Check the /right identity/ law hold for the given 'Monoid' 'Series':+-- | Check the /right identity/ law holds for the given 'Monoid' 'Series': -- -- @ -- x '<>' 'mempty' ≡ x@@ -40,25 +45,47 @@ => Series m a -> Property m rightIdentity s = over s $ \x -> x <> mempty == x --- | Check the /associativity/ law hold for the given 'Monoid' 'Series':+-- * Associativity++-- | Check the /associativity/ law holds for the given 'Monoid' 'Series': -- -- @ -- x '<>' (y '<>' z) ≡ (x '<>' y) '<>' z -- @+--+-- This uses the product of the 3 'Series', be aware of combinatorial explosion. associativity :: (Eq a, Monad m, Show a, Monoid a) => Series m a -> Series m a -> Series m a -> Property m associativity xs ys zs =+ over xs $ \x ->+ over ys $ \y ->+ over zs $ \z ->+ x <> (y <> z) == (x <> y) <> z++-- | Check the /associativity/ law hold for the given 'Monoid' 'Series':+--+-- @+-- x '<>' (y '<>' z) ≡ (x '<>' y) '<>' z+-- @+--+-- This uses the sum of the 3 'Series'.+associativitySum+ :: (Eq a, Monad m, Show a, Monoid a)+ => Series m a -> Series m a -> Series m a -> Property m+associativitySum xs ys zs = over (zipLogic3 xs ys zs) $ \(x,y,z) -> x <> (y <> z) == (x <> y) <> z --- | Check the /mconcat/ law hold for the given 'Monoid' 'Series':+-- * mconcat++-- | When implementing 'mconcat' yourself this must hold: -- -- @ -- 'mconcat' ≡ 'foldr' 'mappend' 'mempty' -- @-mconcat+mconcatProp :: (Eq a, Monad m, Show a, Monoid a) => Series m a -> Property m-mconcat s = over (sequenceA $ replicate 3 s) $ \l ->+mconcatProp s = over (sequenceA $ replicate 3 s) $ \l -> Monoid.mconcat l == foldr mappend mempty l
smallcheck-laws.cabal view
@@ -1,13 +1,15 @@ name: smallcheck-laws-version: 0.2+version: 0.3 synopsis: SmallCheck properties for common laws description:- 'smallcheck' properties for 'Monoid', 'Functor', 'Applicative' and 'Monad'- laws.+ 'smallcheck' properties for testing 'Monoid', 'Functor', 'Applicative' and+ 'Monad' laws. license: BSD3 license-file: LICENSE author: Danny Navarro maintainer: j@dannynavarro.net+homepage: http://github.com/jdnavarro/smallcheck-laws+bug-reports: http://github.com/jdnavarro/smallcheck-laws/issues category: Testing build-type: Simple cabal-version: >=1.10