diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,11 @@
+# Change Log
+All notable changes to this project will be documented in this file. This file
+follows the formatting recommendations from [Keep a
+CHANGELOG](http://keepachangelog.com/). This project adheres to [Semantic
+Versioning](http://semver.org/).
+
+## [0.1]
+### Added
+- Monoid Laws.
+
+[0.1]: https://github.com/jdnavarro/smallcheck-laws/compare/ROOT...v0.1
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2015, J. Daniel Navarro
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of J. Daniel Navarro nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,26 @@
+# SmallCheck Laws
+
+[![Hackage Version](https://img.shields.io/hackage/v/smallcheck-laws.svg)](https://hackage.haskell.org/package/smallcheck-laws) [![Build Status](https://img.shields.io/travis/jdnavarro/smallcheck-laws.svg)](https://travis-ci.org/jdnavarro/smallcheck-laws)
+
+Automatic `smallcheck` properties and `tasty` runners for:
+
+ - Monoid laws.
+ - Functor laws.
+ - Applicative laws.
+ - Monad laws.
+
+## Installation
+
+Make sure you have [`stack`](https://github.com/commercialhaskell/stack)
+installed. Then type:
+
+```sh
+$ stack build
+```
+To run the test suite type:
+
+```sh
+$ stack test
+```
+
+<!-- TODO: Write minitutorial here about to use 'tasty' orphan instances -->
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/Test/SmallCheck/Laws/Applicative.hs b/Test/SmallCheck/Laws/Applicative.hs
new file mode 100644
--- /dev/null
+++ b/Test/SmallCheck/Laws/Applicative.hs
@@ -0,0 +1,85 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+module Test.SmallCheck.Laws.Applicative
+  (
+  -- * Applicative laws
+    identity
+  , composition
+  , homomorphism
+  , interchange
+  ) where
+
+#if !MIN_VERSION_base(4,8,0)
+import Control.Applicative (Applicative, (<$>), (<*>), pure)
+#endif
+import Data.Proxy (Proxy)
+import Data.Functor.Identity (Identity)
+import Test.SmallCheck (Property, over)
+import Test.SmallCheck.Series (Serial, Series)
+import Test.SmallCheck.Series.Utils (zipLogic, zipLogic3)
+
+-- | Check the /identity/ law hold for the given 'Applicative' 'Series':
+--
+-- @
+-- 'pure' id '<*>' v ≡ v
+-- @
+identity
+  :: (Eq (f a), Monad m, Show (f a), Applicative f)
+  => Series m (f a) -> Property m
+identity xs = over xs $ \x -> (pure id <*> x) == x
+
+-- | Check the /composition/ law hold for the given 'Applicative' 'Series':
+--
+-- @
+-- '(.)' '<$>' u '<*>' v '<*>' w ≡  u '<*>' (v '<*>' w)
+-- @
+composition
+  :: ( 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
+composition 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)
+-- @
+homomorphism
+  :: 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
+homomorphism _ 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
+-- @
+interchange
+  :: ( Eq (f b)
+     , Monad m
+     , Show a
+     , Show (f (a -> b))
+     , Applicative f
+     )
+  => Series m a -> Series m (f (a -> b)) -> Property m
+interchange ys us = over (zipLogic ys us) $ \(y,u) ->
+    (u <*> pure y) == (pure ($ y) <*> u)
diff --git a/Test/SmallCheck/Laws/Functor.hs b/Test/SmallCheck/Laws/Functor.hs
new file mode 100644
--- /dev/null
+++ b/Test/SmallCheck/Laws/Functor.hs
@@ -0,0 +1,36 @@
+{-# LANGUAGE FlexibleContexts #-}
+module Test.SmallCheck.Laws.Functor
+  (
+  -- * Functor laws
+    identity
+  , composition
+  ) where
+
+import Data.Functor.Identity (Identity)
+import Test.SmallCheck (Property, over)
+import Test.SmallCheck.Series (Serial, Series)
+import Test.SmallCheck.Series.Utils (zipLogic3)
+
+-- | Check the /identity/ law hold for the given 'Functor' 'Series':
+--
+-- @
+-- 'fmap' 'id' ≡ 'id'
+-- @
+identity
+  :: (Eq (f a), Monad m, Show (f a), Functor f)
+  => Series m (f a) -> Property m
+identity s = over s $ \x -> fmap id x == x
+
+-- | Check the /composition/ law hold for the given 'Functor' 'Series':
+--
+-- @
+-- 'fmap' (f . g) ≡ 'fmap' f . 'fmap' g
+-- @
+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) ->
+    fmap (f . g) x == (fmap f . fmap g) x
diff --git a/Test/SmallCheck/Laws/Monad.hs b/Test/SmallCheck/Laws/Monad.hs
new file mode 100644
--- /dev/null
+++ b/Test/SmallCheck/Laws/Monad.hs
@@ -0,0 +1,48 @@
+{-# LANGUAGE FlexibleContexts #-}
+{-|
+Provided a 'Monad' is already an 'Applicative' there is no need to check the
+first 2 monad laws. See
+@<https://hackage.haskell.org/package/semigroupoids-5.0.0.2/docs/Data-Functor-Bind.html#t:Bind Bind>@
+for which laws are exclusive for the '>>=' method.
+-}
+module Test.SmallCheck.Laws.Monad
+  (
+  -- * Monad laws
+    associativity
+  ) where
+
+import Control.Monad ((>=>))
+import Data.Functor.Identity (Identity)
+
+import Test.SmallCheck (Property, over)
+import Test.SmallCheck.Series (Serial, Series)
+import Test.SmallCheck.Series.Utils (zipLogic3)
+
+-- | 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)
+-- @
+--
+-- Assuming 'join' is the default implementation of 'Monad'.
+
+-- 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
+  :: ( 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 (zipLogic3 ms fs gs) $ \(m,f,g) ->
+    (m >>= f >>= g) == (m >>= (f >=> g))
diff --git a/Test/SmallCheck/Laws/Monoid.hs b/Test/SmallCheck/Laws/Monoid.hs
new file mode 100644
--- /dev/null
+++ b/Test/SmallCheck/Laws/Monoid.hs
@@ -0,0 +1,64 @@
+{-# LANGUAGE CPP #-}
+module Test.SmallCheck.Laws.Monoid
+  (
+  -- * Monoid laws
+    leftIdentity
+  , rightIdentity
+  , associativity
+  , mconcat
+  ) where
+
+#if MIN_VERSION_base(4,8,0)
+import Prelude hiding (mconcat)
+#else
+import Data.Monoid (Monoid, mappend, mempty)
+import Data.Traversable (sequenceA)
+#endif
+import Data.Monoid ((<>))
+import qualified Data.Monoid as Monoid (mconcat)
+import Test.SmallCheck (Property, over)
+import Test.SmallCheck.Series (Series)
+import Test.SmallCheck.Series.Utils (zipLogic3)
+
+-- | Check the /left identity/ law hold for the given 'Monoid' 'Series':
+--
+-- @
+-- 'mempty' '<>' x ≡ x
+-- @
+leftIdentity
+  :: (Eq a, Monad m, Show a, Monoid a)
+  => Series m a -> Property m
+leftIdentity s = over s $ \x -> mempty <> x == x
+
+-- | Check the /right identity/ law hold for the given 'Monoid' 'Series':
+--
+-- @
+-- x '<>' 'mempty' ≡ x
+-- @
+rightIdentity
+  :: (Eq a, Monad m, Show a, Monoid a)
+  => Series m a -> Property m
+rightIdentity s = over s $ \x -> x <> mempty == x
+
+-- | Check the /associativity/ law hold for the given 'Monoid' 'Series':
+--
+-- @
+-- x '<>' (y '<>' z) ≡ (x '<>' y) '<>' z
+-- @
+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 (zipLogic3 xs ys zs) $ \(x,y,z) ->
+        x <> (y <> z) == (x <> y) <> z
+
+-- | Check the /mconcat/ law hold for the given 'Monoid' 'Series':
+--
+-- @
+-- 'mconcat' ≡ 'foldr' 'mappend' 'mempty'
+-- @
+mconcat
+  :: (Eq a, Monad m, Show a, Monoid a)
+  => Series m a -> Property m
+mconcat s = over (sequenceA $ replicate 3 s) $ \l ->
+    Monoid.mconcat l == foldr mappend mempty l
diff --git a/Test/Tasty/SmallCheck/Laws/Applicative.hs b/Test/Tasty/SmallCheck/Laws/Applicative.hs
new file mode 100644
--- /dev/null
+++ b/Test/Tasty/SmallCheck/Laws/Applicative.hs
@@ -0,0 +1,49 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+module Test.Tasty.SmallCheck.Laws.Applicative where
+
+#if !MIN_VERSION_base(4,8,0)
+import Control.Applicative (Applicative)
+#endif
+import Data.Functor.Identity (Identity)
+import Data.Proxy (Proxy(..))
+import Test.Tasty (TestTree, testGroup)
+import Test.Tasty.SmallCheck (testProperty)
+import Test.SmallCheck.Series (Series, Serial(series))
+
+import qualified Test.SmallCheck.Laws.Applicative as Applicative
+import Test.Tasty.SmallCheck.Laws.Functor
+
+-- | @tasty@ 'TestTree' for 'Applicative' laws. You need to provide the type
+--   wrapped in a `Proxy` and make sure 'a' is an instance of 'Serial'.
+testApplicative
+  :: forall f a .
+     ( Applicative f
+     , Show a, Eq a
+     , Show (f a), Eq (f a), (Eq (f (f a)))
+     , Show (f (a -> a))
+     , Serial IO a
+     , Serial IO (f a)
+     , Serial IO (a -> a)
+     , Serial IO (f (a -> a))
+     , Serial Identity a, Serial Identity (f a)
+     )
+  => Proxy (f a) -> TestTree
+testApplicative proxy = testGroup "Applicative"
+  [ testFunctor proxy
+  , testProperty "pure id <*> v ≡ v"
+  $ Applicative.identity (series :: Series IO (f a))
+  , testProperty "(.) <$> u <*> v <*> w ≡  u <*> (v <*> w)"
+  $ Applicative.composition
+      (series :: Series IO (f (a -> a)))
+      (series :: Series IO (f a))
+      (series :: Series IO (f (a -> a)))
+  , testProperty "pure f <*> pure x ≡ pure (f x)" $ Applicative.homomorphism
+      (Proxy :: Proxy f)
+      (series :: Series IO a)
+      (series :: Series IO (a -> a))
+  , testProperty "u <*> pure y ≡ pure ($ y) <*> u" $ Applicative.interchange
+      (series :: Series IO a)
+      (series :: Series IO (f (a -> a)))
+  ]
diff --git a/Test/Tasty/SmallCheck/Laws/Functor.hs b/Test/Tasty/SmallCheck/Laws/Functor.hs
new file mode 100644
--- /dev/null
+++ b/Test/Tasty/SmallCheck/Laws/Functor.hs
@@ -0,0 +1,29 @@
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+module Test.Tasty.SmallCheck.Laws.Functor where
+
+import Data.Proxy (Proxy)
+import Data.Functor.Identity (Identity)
+import Test.Tasty (TestTree, testGroup)
+import Test.Tasty.SmallCheck (testProperty)
+import Test.SmallCheck.Series (Serial(series), Series)
+
+import qualified Test.SmallCheck.Laws.Functor as Functor
+
+-- | @tasty@ 'TestTree' for 'Functor' laws. You need to provide the type
+--   wrapped in a `Proxy` and make sure 'a' is an instance of 'Serial'.
+testFunctor
+  :: forall f a .
+     ( Eq (f a), Eq (f (f a)), Functor f, Show a, Show (f a)
+     , Serial IO (f a)
+     , Serial IO (a -> a)
+     , Serial Identity a, Serial Identity (f a)
+     )
+  => Proxy (f a) -> TestTree
+testFunctor _ = testGroup "Functor laws"
+  [ testProperty "fmap id ≡ id" $ Functor.identity (series :: Series IO (f a))
+  , testProperty "fmap (f . g) ≡ fmap f . fmap g" $ Functor.composition
+      (series :: Series IO (f a))
+      (series :: Series IO (a -> a))
+      (series :: Series IO (a -> a))
+  ]
diff --git a/Test/Tasty/SmallCheck/Laws/Monad.hs b/Test/Tasty/SmallCheck/Laws/Monad.hs
new file mode 100644
--- /dev/null
+++ b/Test/Tasty/SmallCheck/Laws/Monad.hs
@@ -0,0 +1,36 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+module Test.Tasty.SmallCheck.Laws.Monad where
+
+#if !MIN_VERSION_base(4,8,0)
+import Control.Applicative (Applicative)
+#endif
+import Data.Functor.Identity (Identity)
+import Data.Proxy (Proxy(..))
+import Test.SmallCheck.Series (Series, Serial(series))
+import Test.Tasty (TestTree, testGroup)
+import Test.Tasty.SmallCheck (testProperty)
+
+import Test.Tasty.SmallCheck.Laws.Applicative
+import qualified Test.SmallCheck.Laws.Monad as Monad
+
+-- | @tasty@ 'TestTree' for 'Monad' laws. You need to provide the type
+--   wrapped in a `Proxy` and make sure 'a' is an instance of 'Serial'.
+testMonad
+  :: forall f a .
+     ( Applicative f, Monad f
+     , Show a, Show (f a), Show (f (a -> a))
+     , Eq a, Eq (f a), Eq (f (f a))
+     , Serial IO a, Serial IO (a -> a)
+     , Serial IO (f a) ,Serial IO (f (a -> a)), Serial IO (a -> f a)
+     , Serial Identity a, Serial Identity (f a)
+     )
+  => Proxy (f a) -> TestTree
+testMonad proxy = testGroup "Monad laws"
+  [ testApplicative proxy
+  , testProperty "(m >>= f) >>= g ≡ m (f >=> g)"
+  $ Monad.associativity (series :: Series IO (f a))
+                        (series :: Series IO (a -> f a))
+                        (series :: Series IO (a -> f a))
+  ]
diff --git a/Test/Tasty/SmallCheck/Laws/Monoid.hs b/Test/Tasty/SmallCheck/Laws/Monoid.hs
new file mode 100644
--- /dev/null
+++ b/Test/Tasty/SmallCheck/Laws/Monoid.hs
@@ -0,0 +1,26 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+module Test.Tasty.SmallCheck.Laws.Monoid where
+
+#if !MIN_VERSION_base(4,8,0)
+import Data.Monoid (Monoid)
+#endif
+import Data.Proxy (Proxy)
+import Test.SmallCheck.Series (Series, Serial(series))
+import Test.Tasty (TestTree, testGroup)
+import Test.Tasty.SmallCheck (testProperty)
+
+import qualified Test.SmallCheck.Laws.Monoid as Monoid
+
+-- | @tasty@ 'TestTree' for 'Applicative' laws. You need to provide the type
+--   wrapped in a `Proxy` and make sure 'a' is an instance of 'Serial'.
+testMonoid :: forall a . (Show a, Eq a, Monoid a, Serial IO a) => Proxy a -> TestTree
+testMonoid _ = testGroup "Monoid laws"
+  [ testProperty "mempty <> x ≡ x" $ Monoid.leftIdentity (series :: Series IO a)
+  , testProperty "x <> mempty ≡ x" $ Monoid.rightIdentity (series :: Series IO a)
+  , testProperty "x <> (y <> z) ≡ (x <> y) <> z"
+  $ Monoid.associativity (series :: Series IO a) series series
+  , testProperty "mconcat ≡ foldr mappend mempty"
+  $ Monoid.mconcat (series :: Series IO a)
+  ]
diff --git a/smallcheck-laws.cabal b/smallcheck-laws.cabal
new file mode 100644
--- /dev/null
+++ b/smallcheck-laws.cabal
@@ -0,0 +1,67 @@
+name:                smallcheck-laws
+version:             0.1
+synopsis:            SmallCheck properties for standard type classes
+description:
+  Automatic `smallcheck` properties and `tasty` runners for:
+  .
+  - Monoid laws.
+  - Functor laws.
+  - Applicative laws.
+  - Monad laws.
+  .
+  Use the @<https://hackage.haskell.org/package/tasty Tasty>@ modules for
+  preassembled tasty runners, your data types need to be instances of
+  @<https://hackage.haskell.org/package/smallcheck-1.1.1/docs/Test-SmallCheck-Series.html#t:Serial Serial>@.
+  For more granular control on how the
+  @<https://hackage.haskell.org/package/smallcheck SmallCheck>@
+  @<https://hackage.haskell.org/package/smallcheck-1.1.1/docs/Test-SmallCheck-Series.html#t:Series Series>@
+  are created use the modules under @Test.SmallCheck.Laws@.
+license:             BSD3
+license-file:        LICENSE
+author:              Danny Navarro
+maintainer:          j@dannynavarro.net
+category:            Testing
+build-type:          Simple
+cabal-version:       >=1.10
+extra-source-files:  README.md CHANGELOG.md
+                     stack.yaml
+
+source-repository head
+  type: git
+  location: git://github.com/jdnavarro/smallcheck-laws.git
+
+library
+  ghc-options:         -Wall
+  default-language:    Haskell2010
+  exposed-modules:     Test.SmallCheck.Laws.Applicative,
+                       Test.SmallCheck.Laws.Functor,
+                       Test.SmallCheck.Laws.Monad,
+                       Test.SmallCheck.Laws.Monoid,
+                       Test.Tasty.SmallCheck.Laws.Applicative,
+                       Test.Tasty.SmallCheck.Laws.Functor,
+                       Test.Tasty.SmallCheck.Laws.Monad,
+                       Test.Tasty.SmallCheck.Laws.Monoid
+  build-depends:       base >=4.6 && <4.9,
+                       smallcheck >=1.1.1,
+                       smallcheck-series >=0.3,
+                       tasty >=0.10,
+                       tasty-smallcheck >=0.8
+  if impl(ghc < 7.10)
+     build-depends: transformers >=0.3.0.0
+
+  if impl(ghc < 7.8)
+     build-depends: tagged >=0.7.2
+
+test-suite tasty
+  default-language:    Haskell2010
+  type:                exitcode-stdio-1.0
+  hs-source-dirs:      tests
+  main-is:             tasty.hs
+  ghc-options:         -Wall -threaded
+  build-depends:       base >=4.6 && <4.9,
+                       smallcheck >=1.1,
+                       tasty >=0.10,
+                       smallcheck-laws
+
+  if impl(ghc < 7.8)
+     build-depends: tagged >=0.7.2
diff --git a/stack.yaml b/stack.yaml
new file mode 100644
--- /dev/null
+++ b/stack.yaml
@@ -0,0 +1,6 @@
+flags: {}
+packages:
+- '.'
+extra-deps:
+- smallcheck-series-0.3
+resolver: lts-2.21
diff --git a/tests/tasty.hs b/tests/tasty.hs
new file mode 100644
--- /dev/null
+++ b/tests/tasty.hs
@@ -0,0 +1,99 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+module Main where
+
+#if !MIN_VERSION_base(4,8,0)
+import Control.Applicative ((<$>))
+#endif
+import Data.Monoid (Sum(..), Product(..))
+import Data.Proxy (Proxy(..))
+
+import Test.SmallCheck.Series (Serial(series))
+import Test.Tasty (TestTree, defaultMain, testGroup)
+
+import Test.Tasty.SmallCheck.Laws.Applicative
+import Test.Tasty.SmallCheck.Laws.Functor
+import Test.Tasty.SmallCheck.Laws.Monad
+import Test.Tasty.SmallCheck.Laws.Monoid
+
+main :: IO ()
+main = defaultMain $ testGroup "Laws"
+     [ monoidTests
+     , functorTests
+     , applicativeTests
+     , monadTests
+     ]
+
+monoidTests :: TestTree
+monoidTests = testGroup "Monoid"
+  [ testGroup "Sum"
+    [ testGroup "Int"
+      [ testMonoid (Proxy :: Proxy (Sum Int)) ]
+    , testGroup "Integer"
+      [ testMonoid (Proxy :: Proxy (Sum Integer)) ]
+    , testGroup "Float"
+      [ testMonoid (Proxy :: Proxy (Sum Float)) ]
+    ]
+  , testGroup "Product"
+     [ testGroup "Int"
+      [ testMonoid (Proxy :: Proxy (Product Int)) ]
+    , testGroup "Integer"
+      [ testMonoid (Proxy :: Proxy (Product Integer)) ]
+    , testGroup "Float"
+      [ testMonoid (Proxy :: Proxy (Product Float)) ]
+    ]
+  ]
+
+functorTests :: TestTree
+functorTests = testGroup "Functor"
+  [ testGroup "Maybe"
+    [ testGroup "Int"
+      [ testFunctor (Proxy :: Proxy (Maybe Int)) ]
+    , testGroup "Char"
+      [ testFunctor (Proxy :: Proxy (Maybe Char)) ]
+    ]
+  , testGroup "[]"
+    [ testGroup "Bool"
+      [ testFunctor (Proxy :: Proxy [Bool]) ]
+    , testGroup "Int"
+      [ testFunctor (Proxy :: Proxy [Int]) ]
+    ]
+  ]
+
+applicativeTests :: TestTree
+applicativeTests = testGroup "Applicative"
+  [ testGroup "Maybe"
+    [ testGroup "Int"
+      [ testApplicative (Proxy :: Proxy (Maybe Int)) ]
+    , testGroup "Float"
+      [ testApplicative (Proxy :: Proxy (Maybe Float)) ]
+    ]
+  , testGroup "[]"
+    [ testGroup "Bool"
+      [ testApplicative (Proxy :: Proxy [Bool]) ]
+    , testGroup "Char"
+      [ testApplicative (Proxy :: Proxy [Char]) ]
+    ]
+  ]
+
+monadTests :: TestTree
+monadTests = testGroup "Monad"
+  [ testGroup "Maybe"
+    [ testGroup "()"
+      [ testMonad (Proxy :: Proxy (Maybe ())) ]
+    , testGroup "Int"
+      [ testMonad (Proxy :: Proxy (Maybe Int)) ]
+    ]
+  , testGroup "[]"
+    [ testGroup "()"
+      [ testMonad (Proxy :: Proxy [()]) ]
+    ]
+  ]
+
+instance (Monad m, Serial m a) => Serial m (Sum a) where
+    series = Sum <$> series
+
+instance (Monad m, Serial m a) => Serial m (Product a) where
+    series = Product <$> series
