packages feed

smallcheck-laws 0.2 → 0.3

raw patch · 7 files changed

+198/−19 lines, 7 files

Files

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 @@ [![Build Status](https://img.shields.io/travis/jdnavarro/smallcheck-laws.svg)](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