packages feed

hedgehog-classes (empty) → 0.1.0.0

raw patch · 43 files changed

+4801/−0 lines, 43 filesdep +aesondep +basedep +containers

Dependencies added: aeson, base, containers, hedgehog, pretty-show, transformers, wl-pprint-annotated

Files

+ CHANGELOG.md view
@@ -0,0 +1,12 @@+# Changelog++`hedgehog-classes` uses [PVP Versioning][1].+The changelog is available [on GitHub][2].++0.0.0+=====++* Initially created.++[1]: https://pvp.haskell.org+[2]: https://github.com/chessai/hedgehog-classes/releases
+ LICENSE view
@@ -0,0 +1,29 @@+BSD 3-Clause License++Copyright (c) 2019, chessai+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 the copyright holder nor the names of its+  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 HOLDER 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.
+ README.md view
@@ -0,0 +1,8 @@+# hedgehog-classes++[![Hackage](https://img.shields.io/hackage/v/hedgehog-classes.svg)](https://hackage.haskell.org/package/hedgehog-classes)+[![BSD3 license](https://img.shields.io/badge/license-BSD3-blue.svg)](LICENSE)+<!--- [![Stackage Lts](http://stackage.org/package/hedgehog-classes/badge/lts)](http://stackage.org/lts/package/hedgehog-classes)--->+<!--- [![Stackage Nightly](http://stackage.org/package/hedgehog-classes/badge/nightly)](http://stackage.org/nightly/package/hedgehog-classes) --->++Hedgehog will eat your typeclass bugs
+ hedgehog-classes.cabal view
@@ -0,0 +1,186 @@+cabal-version: 2.0+name: +  hedgehog-classes+version:+  0.1.0.0+synopsis:+  Hedgehog will eat your typeclass bugs+description:+  This library provides Hedgehog properties to ensure+  that typeclass instances adhere to the set of laws+  that they are supposed to. There are other libraries+  that do similar things, such as `genvalidity-hspec` and `checkers`.+  This library differs from other solutions by not introducing any+  new typeclasses that the user needs to learn, and otherwise minimal+  API overhead.+  .+  This library is directly inspired by `quickcheck-classes`.+homepage:+  https://github.com/chessai/hedgehog-classes+bug-reports:+  https://github.com/chessai/hedgehog-classes/issues+license:+  BSD3+license-file:+  LICENSE+author:+  chessai+maintainer:+  chessai1996@gmail.com+copyright:+  2019 chessai+category:+  Testing+build-type:+  Simple+extra-doc-files:+    README.md+  , CHANGELOG.md+tested-with: GHC == 8.6.1, GHC == 8.6.2, GHC == 8.6.3++source-repository head+  type:                git+  location:            https://github.com/chessai/hedgehog-classes.git++flag aeson+  description:+    You can disable the use of the `aeson` package using `-f-aeson`.+    .+    This may be useful for accelerating builds in sandboxes for expert users.+  default: True+  manual: True++-- flag semigroupoids+--   description:+--     You can disable the use of the `semirings` package using `-f-semirings`.+--     .+--     This may be useful for accelerating builds in sandboxes for expert users.+--   default: True+--   manual: True++-- flag semirings+--   description:+--     You can disable the use of the `semirings` package using `-f-semirings`.+--     .+--     This may be useful for accelerating builds in sandboxes for expert users.+--   default: True+--   manual: True++library+  hs-source-dirs:+    src+  exposed-modules:+    Hedgehog.Classes+  other-modules:+    Hedgehog.Classes.Alternative+    Hedgehog.Classes.Applicative+    Hedgehog.Classes.Arrow+    Hedgehog.Classes.Bifoldable+    Hedgehog.Classes.Bifunctor+    Hedgehog.Classes.Bitraversable+    Hedgehog.Classes.Bits+    Hedgehog.Classes.Category+    Hedgehog.Classes.Common+      Hedgehog.Classes.Common.ApTrans+      Hedgehog.Classes.Common.Bottom+      Hedgehog.Classes.Common.Compat+      Hedgehog.Classes.Common.Equation+      Hedgehog.Classes.Common.Func+      Hedgehog.Classes.Common.Gen+      Hedgehog.Classes.Common.IO+      Hedgehog.Classes.Common.Laws+      Hedgehog.Classes.Common.Property+      Hedgehog.Classes.Common.PP+    Hedgehog.Classes.Contravariant+    Hedgehog.Classes.Enum+    Hedgehog.Classes.Eq+    Hedgehog.Classes.Foldable+    Hedgehog.Classes.Functor+    Hedgehog.Classes.Generic+    Hedgehog.Classes.Integral+--    Hedgehog.Classes.Ix+    Hedgehog.Classes.Json+    Hedgehog.Classes.Monad+--    Hedgehog.Classes.MonadFix+    Hedgehog.Classes.MonadIO+    Hedgehog.Classes.MonadPlus+    Hedgehog.Classes.MonadZip+    Hedgehog.Classes.Monoid+    Hedgehog.Classes.Ord+    Hedgehog.Classes.Semigroup+--    Hedgehog.Classes.Semiring+    Hedgehog.Classes.Show+    Hedgehog.Classes.ShowRead+    Hedgehog.Classes.Storable+    Hedgehog.Classes.Traversable+  build-depends:+      base                >= 4.12.0.0 && < 4.14.0.0+    , hedgehog            >= 0.5.0.0  && < 0.7.0.0+    , containers          >= 0.5.9.2  && < 0.7.0.0+    , pretty-show         >= 1.6.0.0  && < 2.0.0.0+    , transformers        >= 0.5.0.0  && < 0.6.0.0+    , wl-pprint-annotated >= 0.0.0.0  && < 0.2.0.0+  ghc-options:+    -Wall+  default-language:+    Haskell2010+  if impl(ghc < 8.5)+    buildable: False+  if impl(ghc >= 8.5)+    cpp-options: -DHAVE_QUANTIFIED_CONSTRAINTS+  if flag(aeson)+    build-depends: aeson >= 0.9.0.0 && < 1.5.0.0+    cpp-options: -DHAVE_AESON+--  if flag(semigroupoids)+--    build-depends: semigroupoids >= 0.5.3.0 && < 0.6.0.0+--    cpp-options: -DHAVE_SEMIGROUPOIDS+--  if flag(semirings)+--    build-depends: semirings >= 0.3.1.1 && < 0.4.0.0+--    cpp-options: -DHAVE_SEMIRINGS+--  if flag(vector)+--    build-depends: vector >= 0.12.0.0 && < 0.13.0.0 +--    cpp-options: -DHAVE_VECTOR+ +--test-suite spec+--  type:                exitcode-stdio-1.0+--  hs-source-dirs:      test+--  main-is:             Spec.hs+--+--  other-modules:       Spec.Alternative+--                       Spec.Applicative+--                       Spec.Arrow+--                       Spec.Bifoldable+--                       Spec.Bifunctor+--                       Spec.Bitraversable+--                       Spec.Bits+--                       Spec.Category+--                       Spec.Contravariant+--                       Spec.Enum+--                       Spec.Eq+--                       Spec.Foldable+--                       Spec.Functor+--                      Spec.Generic+--                       Spec.Integral+--                       Spec.Ix+--                       Spec.Json+--                       Spec.Monad+--                       Spec.MonadIO+--                       Spec.MonadPlus+--                       Spec.MonadZip+--                       Spec.Monoid+--                       Spec.Ord+--                       Spec.Semigroup+--                       Spec.Show+--                       Spec.ShowRead+--                       Spec.Storable+--                       Spec.Traversable+--+--  build-depends:       base >= 4.12.0.0 && < 4.13+--                     , aeson +--                     , containers +--                     , hedgehog +--                     , hedgehog-classes+--+--  ghc-options:         -Wall+-- +--  default-language:    Haskell2010
+ src/Hedgehog/Classes.hs view
@@ -0,0 +1,102 @@+{-| This library provides sets of properties that should hold for common+    typeclasses.++    /Note:/ on GHC < 8.5, this library uses the higher-kinded typeclasses+    ('Data.Functor.Classes.Show1', 'Data.Functor.Classes.Eq1', 'Data.Functor.Classes.Ord1', etc.),+    but on GHC >= 8.5, it uses `-XQuantifiedConstraints` to express these+    constraints more cleanly.+-}+module Hedgehog.Classes+  ( -- * Running+    lawsCheck+  , lawsCheckOne+  , lawsCheckMany++    -- * Properties+    -- ** Ground types+  , bitsLaws+  , eqLaws+  , integralLaws+  , monoidLaws+  , commutativeMonoidLaws+  , ordLaws+--  , ixLaws+  , enumLaws+  , boundedEnumLaws+  , semigroupLaws+  , commutativeSemigroupLaws+  , exponentialSemigroupLaws+  , idempotentSemigroupLaws+  , rectangularBandSemigroupLaws+  , showLaws+  , showReadLaws+  , storableLaws+  , genericLaws+  , jsonLaws++    -- ** Unary type constructors+  , alternativeLaws+  , applicativeLaws+  , contravariantLaws +  , foldableLaws+  , functorLaws+  , monadLaws+--  , monadFixLaws+  , monadIOLaws+  , monadPlusLaws+  , monadZipLaws+  , traversableLaws++    -- ** Binary type constructors+  , arrowLaws+  , bifoldableLaws+  , bifoldableFunctorLaws+  , bifunctorLaws+  , bitraversableLaws+  , categoryLaws+  , commutativeCategoryLaws++    -- * Defining your own laws+  , Laws(..)+  , LawContext(..)+  , Context(..)+  , contextualise++    -- * Hedgehog equality tests sans source information+  , hLessThan, hGreaterThan+  , heq, heq1, heq2+  , heqCtx, heqCtx1, heqCtx2+  , hneq, hneq1, hneq2+  , hneqCtx, hneqCtx1, hneqCtx2+  ) where++import Hedgehog.Classes.Alternative (alternativeLaws)+import Hedgehog.Classes.Applicative (applicativeLaws)+import Hedgehog.Classes.Arrow (arrowLaws)+import Hedgehog.Classes.Bifoldable (bifoldableLaws, bifoldableFunctorLaws)+import Hedgehog.Classes.Bifunctor (bifunctorLaws)+import Hedgehog.Classes.Bitraversable (bitraversableLaws)+import Hedgehog.Classes.Bits (bitsLaws)+import Hedgehog.Classes.Category (categoryLaws, commutativeCategoryLaws)+import Hedgehog.Classes.Common+import Hedgehog.Classes.Contravariant (contravariantLaws)+import Hedgehog.Classes.Enum (enumLaws, boundedEnumLaws)+import Hedgehog.Classes.Eq (eqLaws)+import Hedgehog.Classes.Foldable (foldableLaws)+import Hedgehog.Classes.Functor (functorLaws)+import Hedgehog.Classes.Generic (genericLaws)+import Hedgehog.Classes.Integral (integralLaws)+--import Hedgehog.Classes.Ix (ixLaws)+import Hedgehog.Classes.Json (jsonLaws)+import Hedgehog.Classes.Monad (monadLaws)+import Hedgehog.Classes.MonadIO (monadIOLaws)+import Hedgehog.Classes.MonadPlus (monadPlusLaws)+import Hedgehog.Classes.MonadZip (monadZipLaws)+import Hedgehog.Classes.Monoid (monoidLaws, commutativeMonoidLaws)+import Hedgehog.Classes.Ord (ordLaws)+import Hedgehog.Classes.Semigroup (semigroupLaws, commutativeSemigroupLaws, exponentialSemigroupLaws, idempotentSemigroupLaws, rectangularBandSemigroupLaws)+import Hedgehog.Classes.Show (showLaws)+import Hedgehog.Classes.ShowRead (showReadLaws)+import Hedgehog.Classes.Storable (storableLaws)+import Hedgehog.Classes.Traversable (traversableLaws)+ 
+ src/Hedgehog/Classes/Alternative.hs view
@@ -0,0 +1,85 @@+{-# LANGUAGE ScopedTypeVariables   #-}+{-# LANGUAGE QuantifiedConstraints #-}+{-# LANGUAGE RankNTypes            #-}++module Hedgehog.Classes.Alternative (alternativeLaws) where++import Control.Applicative (Alternative(..))++import Hedgehog+import Hedgehog.Classes.Common++-- | Tests the following 'Alternative' laws:+-- +-- [__Left Identity__]: @'empty' '<|>' a@ ≡ @a@+-- [__Right Identity__]: @a '<|>' 'empty'@ ≡ @a@+-- [__Associativity__]: @a '<|>' (b '<|>' c)@ ≡ @(a '<|>' b) '<|>' c@+alternativeLaws ::+  ( Alternative f+  , forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)+  ) => (forall x. Gen x -> Gen (f x)) -> Laws+alternativeLaws gen = Laws "Alternative"+  [ ("Left Identity", alternativeLeftIdentity gen)+  , ("Right Identity", alternativeRightIdentity gen)+  , ("Associativity", alternativeAssociativity gen)+  ]++type AlternativeProp f =+  ( Alternative f+  , forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)+  ) => (forall x. Gen x -> Gen (f x)) -> Property++alternativeLeftIdentity :: forall f. AlternativeProp f+alternativeLeftIdentity fgen = property $ do+  a <- forAll $ fgen genSmallInteger+  let lhs = empty <|> a+  let rhs = a+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Left Identity", lawContextLawBody = "empty <|> a" `congruency` "a"+        , lawContextTcName = "Alternative", lawContextTcProp =+            let showA = show a;+            in lawWhere+              [ "empty <|> a" `congruency` "a, where"+              , "a = " ++ showA+              ]+        , lawContextReduced = reduced lhs rhs+        }+  heqCtx1 lhs rhs ctx++alternativeRightIdentity :: forall f. AlternativeProp f+alternativeRightIdentity fgen = property $ do+  a <- forAll $ fgen genSmallInteger+  let lhs = a <|> empty+  let rhs = a+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Right Identity", lawContextLawBody = "a <|> empty" `congruency` "a"+        , lawContextTcName = "Alternative", lawContextTcProp =+            let showA = show a;+            in lawWhere+              [ "a <|> empty" `congruency` "a, where"+              , "a = " ++ showA+              ]+        , lawContextReduced = reduced lhs rhs+        }+  heqCtx1 lhs rhs ctx  ++alternativeAssociativity :: forall f. AlternativeProp f+alternativeAssociativity fgen = property $ do+  a <- forAll $ fgen genSmallInteger+  b <- forAll $ fgen genSmallInteger+  c <- forAll $ fgen genSmallInteger+  let lhs = (a <|> (b <|> c))+  let rhs = ((a <|> b) <|> c)+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Associativity", lawContextLawBody = "a <|> (b <|> c)" `congruency` "(a <|> b) <|> c"+        , lawContextTcName = "Alternative", lawContextTcProp =+            let showA = show a; showB = show b; showC = show c;+            in lawWhere+                 [ "a <|> (b <|> c)" `congruency` "(a <|> b) <|> c), where"+                 , "a = " ++ showA+                 , "b = " ++ showB+                 , "c = " ++ showC+                 ]+        , lawContextReduced = reduced lhs rhs+        }+  heqCtx1 lhs rhs ctx
+ src/Hedgehog/Classes/Applicative.hs view
@@ -0,0 +1,161 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE QuantifiedConstraints #-}+{-# LANGUAGE RankNTypes #-}++module Hedgehog.Classes.Applicative (applicativeLaws) where++import Control.Applicative (Applicative(..))++import Hedgehog+import Hedgehog.Classes.Common++-- | Tests the following 'Applicative' laws:+--+-- [__Identity__]: @'pure' 'id' '<*>' v@ ≡ @v@+-- [__Composition__]: @'pure' ('.') '<*>' u '<*>' v '<*>' w@ ≡ @u '<*>' (v '<*>' w)@+-- [__Homomorphism__]: @'pure' f '<*>' 'pure'@ x ≡ @'pure' (f x)@+-- [__Interchange__]: @u '<*>' 'pure' y@ ≡ @'pure' ('$' y) '<*>' u@+-- [__LiftA2 1__]: @'liftA2' 'id' f x@ ≡ @f '<*>' x@+-- [__LiftA2 2__]: @'liftA2' f x y@ ≡ @f '<$>' x '<*>' y@+applicativeLaws ::+  ( Applicative f+  , forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)+  ) => (forall x. Gen x -> Gen (f x)) -> Laws+applicativeLaws gen = Laws "Applicative"+  [ ("Identity", applicativeIdentity gen)+  , ("Composition", applicativeComposition gen)+  , ("Homomorphism", applicativeHomomorphism gen)+  , ("Interchange", applicativeInterchange gen)+  , ("LiftA2 Part 1", applicativeLiftA2_1 gen)+  , ("LiftA2 Part 2", applicativeLiftA2_2 gen) +  ]++type ApplicativeProp f =+  ( Applicative f+  , forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)+  ) => (forall x. Gen x -> Gen (f x)) -> Property++applicativeIdentity :: forall f. ApplicativeProp f+applicativeIdentity fgen = property $ do+  a <- forAll $ fgen genSmallInteger+  let lhs = pure id <*> a+  let rhs = a+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Identity", lawContextLawBody = "pure id <*> v" `congruency` "v"+        , lawContextTcName = "Applicative", lawContextTcProp =+             let showA = show a+             in lawWhere+                 [ "pure id <*> v" `congruency` "v, where"+                 , "v = " ++ showA+                 ]+        , lawContextReduced = reduced lhs rhs+        }+  heqCtx1 lhs rhs ctx++applicativeComposition :: forall f. ApplicativeProp f+applicativeComposition fgen = property $ do+  u' <- forAll $ fgen genQuadraticEquation+  v' <- forAll $ fgen genQuadraticEquation+  w' <- forAll genSmallInteger+  let u = runQuadraticEquation <$> u'+      v = runQuadraticEquation <$> v'+      w = pure w'+  let lhs = pure (.) <*> u <*> v <*> w+  let rhs = u <*> (v <*> w)+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Composition", lawContextLawBody = "pure (.) <*> u <*> v <*> w == u <*> (v <*> w)"+        , lawContextTcName = "Applicative", lawContextTcProp =+            let showU = show u'; showV = show v'; showW = show w';+            in lawWhere+                 [ "pure (.) <*> u <*> v <*> w", congruent, "u <*> (v <*> w), where"+                 , "u = " ++ showU+                 , "v = " ++ showV+                 , "w = " ++ showW+                 ]+        , lawContextReduced = reduced lhs rhs+        }++  heqCtx1 lhs rhs ctx++applicativeHomomorphism :: forall f. ApplicativeProp f+applicativeHomomorphism _ = property $ do+  e <- forAll genQuadraticEquation+  a <- forAll genSmallInteger+  let f = runQuadraticEquation e+  let lhs = pure f <*> pure a+  let rhs = pure (f a) :: f Integer+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Homomorphism", lawContextLawBody = "pure f <*> pure x" `congruency` "pure (f x)"+        , lawContextTcName = "Applicative", lawContextTcProp =+            let showF = show e; showX = show a;+            in lawWhere+              [ "pure f <*> pure x", congruent, "pure (f x), where"+              , "f = " ++ showF+              , "x = " ++ showX+              ]+        , lawContextReduced = reduced lhs rhs+        }+  heqCtx1 lhs rhs ctx++applicativeInterchange :: forall f. ApplicativeProp f+applicativeInterchange fgen = property $ do+  u' <- forAll $ fgen genQuadraticEquation+  y <- forAll genSmallInteger+  let u = fmap runQuadraticEquation u'+  let lhs = (u <*> pure y)+  let rhs = pure ($ y) <*> u+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Interchange", lawContextLawBody = "u <*> pure y" `congruency` "pure ($ y) <*> u"+        , lawContextTcName = "Applicative", lawContextTcProp =+            let showU = show u'; showY = show y;+            in lawWhere+              [ "u <*> pure y", congruent, "pure ($ y) <*> u, where"+              , "u = " ++ showU+              , "y = " ++ showY+              ]+        , lawContextReduced = reduced lhs rhs+        }+  heqCtx1 lhs rhs ctx++applicativeLiftA2_1 :: forall f. ApplicativeProp f+applicativeLiftA2_1 fgen = property $ do+  f' <- forAll $ fgen genQuadraticEquation+  x <- forAll $ fgen genSmallInteger+  let f = fmap runQuadraticEquation f'+  let lhs = liftA2 id f x+  let rhs = f <*> x+  let ctx = contextualise $ LawContext+        { lawContextLawName = "LiftA2 1", lawContextLawBody = "liftA2 id f x" `congruency` "f <*> x"+        , lawContextTcName = "Applicative", lawContextTcProp =+            let showF = show f'; showX = show x;+            in lawWhere+              [ "liftA2 id f x", congruent, "f <*> x, where"+              , "f = " ++ showF+              , "x = " ++ showX+              ]+        , lawContextReduced = reduced lhs rhs+        }+  heqCtx1 lhs rhs ctx++applicativeLiftA2_2 :: forall f. ApplicativeProp f+applicativeLiftA2_2 fgen = property $ do+  x <- forAll $ fgen genSmallInteger+  y <- forAll $ fgen genSmallInteger+  f' <- forAll $ genLinearEquationTwo+  let f = runLinearEquationTwo f'+  let lhs = liftA2 f x y+  let rhs = f <$> x <*> y+  let ctx = contextualise $ LawContext+        { lawContextLawName = "LiftA2 2", lawContextLawBody = "liftA2 f x y == f <$> x <*> y"+        , lawContextTcName = "Applicative", lawContextTcProp =+            let showF = show f'; showX = show x; showY = show y;+            in lawWhere+              [ "liftA2 f x y" `congruency` "f <$> x <*> y, where"+              , "f = " ++ showF+              , "x = " ++ showX+              , "y = " ++ showY+              ]+        , lawContextReduced = reduced lhs rhs+        }+  heqCtx1 lhs rhs ctx+
+ src/Hedgehog/Classes/Arrow.hs view
@@ -0,0 +1,96 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE QuantifiedConstraints #-}++module Hedgehog.Classes.Arrow (arrowLaws) where++import Hedgehog+import Hedgehog.Classes.Common++import Control.Arrow(Arrow(..), (>>>))+import Control.Category(Category(..))+import Prelude hiding (id, (.))+import qualified Prelude++-- | Tests the following 'Arrow' laws:+--+-- [__Arr Identity__]: @'arr' 'id'@ ≡ @'id'@+-- [__Arr Composition__]: @'arr' (f '>>>' g)@ ≡ @'arr' f '>>>' 'arr' g@+-- [__Arr-First inverse__]: @'first' ('arr' f)@ ≡ @'arr' ('first' f)@+-- [__First Composition__]: @'first' (f '>>>' g)@ ≡ @'first' f '>>>' 'first' g@+-- [__Arrow Law 5__]: @'first' f '>>>' 'arr' 'fst'@ ≡ @'arr' 'fst' '>>>' f@+-- [__Arrow Law 6__]: @'first' f '>>>' 'arr' ('id' '***' g)@ ≡ @'arr' ('id' '***' g) '>>>' 'first' f@+-- [__Arrow Law 7__]: @'first' ('first' f) '>>>' 'arr' assoc@ ≡ @'arr' assoc '>>>' 'first' f, where assoc ((a,b),c) = (a,(b,c))@+arrowLaws :: forall f.+  ( Arrow f+  , forall x y. (Eq x, Eq y) => Eq (f x y)+  , forall x y. (Show x, Show y) => Show (f x y)+  ) => (forall x y. Gen x -> Gen y -> Gen (f x y)) -> Laws+arrowLaws gen = Laws "Arrow"+  [ ("Arr Identity", arrowLaw1 gen)+  , ("Arr Composition", arrowLaw2 gen)+  , ("Arr . First == First . Arr", arrowLaw3 gen)+  , ("First Composition", arrowLaw4 gen)+  , ("Arrow Law 5", arrowLaw5 gen)+  , ("Arrow Law 6", arrowLaw6 gen)+  , ("Arrow Law 7", arrowLaw7 gen)+  ]++type ArrowProp f =+  ( Arrow f+  , forall x y. (Eq x, Eq y) => Eq (f x y)+  , forall x y. (Show x, Show y) => Show (f x y)+  ) => (forall x y. Gen x -> Gen y -> Gen (f x y)) -> Property++arrowLaw1 :: forall f. ArrowProp f+arrowLaw1 _ = property $ do+  arr Prelude.id `heq2` (id :: f Integer Integer)++arrowLaw2 :: forall f. ArrowProp f+arrowLaw2 _ = property $ do+  f' <- forAll genQuadraticEquation+  g' <- forAll genQuadraticEquation+  let f = runQuadraticEquation f'+      g = runQuadraticEquation g'+  (arr (f >>> g) :: f Integer Integer) `heq2` (arr f >>> arr g) ++arrowLaw3 :: forall f. ArrowProp f+arrowLaw3 _ = property $ do+  f' <- forAll genQuadraticEquation+  let f = runQuadraticEquation f'+  let x = first (arr f) :: f (Integer, Integer) (Integer, Integer)+  let y = arr (first f) :: f (Integer, Integer) (Integer, Integer) +  x `heq2` y++arrowLaw4 :: forall f. ArrowProp f+arrowLaw4 fgen = property $ do+  f <- forAll $ fgen genSmallInteger genSmallInteger+  g <- forAll $ fgen genSmallInteger genSmallInteger+  let x = first (f >>> g) :: f (Integer, Integer) (Integer, Integer)+  let y = first f >>> first g :: f (Integer, Integer) (Integer, Integer)+  x `heq2` y ++arrowLaw5 :: forall f. ArrowProp f+arrowLaw5 fgen = property $ do+  f <- forAll $ fgen genSmallInteger genSmallInteger+  let x = first f >>> arr fst :: f (Integer, Integer) Integer+  let y = arr fst >>> f :: f (Integer, Integer) Integer+  x `heq2` y ++arrowLaw6 :: forall f. ArrowProp f+arrowLaw6 fgen = property $ do+  f <- forAll $ fgen genSmallInteger genSmallInteger+  g' <- forAll genQuadraticEquation+  let g = runQuadraticEquation g'+  let x = ((first f) >>> (arr (Prelude.id *** g))) :: f (Integer, Integer) (Integer, Integer) +  let y = arr (id *** g) >>> first f :: f (Integer, Integer) (Integer, Integer) +  x `heq2` y++arrowLaw7 :: forall f. ArrowProp f+arrowLaw7 fgen = property $ do+  let assoc ((a,b),c) = (a,(b,c))+  f <- forAll $ fgen genSmallInteger genSmallInteger+  let x = first (first f) >>> arr assoc :: f ((Integer, Integer), Integer) (Integer, (Integer, Integer))+  let y = arr assoc >>> first f :: f ((Integer, Integer), Integer) (Integer, (Integer, Integer))+  x `heq2` y+
+ src/Hedgehog/Classes/Bifoldable.hs view
@@ -0,0 +1,161 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE QuantifiedConstraints #-}++module Hedgehog.Classes.Bifoldable (bifoldableLaws, bifoldableFunctorLaws) where++import Hedgehog+import Hedgehog.Classes.Common++import Data.Bifoldable (Bifoldable(..))+import Data.Bifunctor (Bifunctor(..))+import Data.Monoid (Endo(..), Sum(..), Product(..))++-- | Tests the following 'Bifoldable' laws:+--+-- [__Identity__]: @'bifold'@ ≡ @'bifoldMap' 'id' 'id'@ +-- [__FoldMap__]: @'bifoldMap' f g@ ≡ @'bifoldr' ('mappend' '.' f) ('mappend' '.' g) 'mempty'@+-- [__Foldr__]: @'bifoldr' f g z t@ ≡ @'appEndo' ('bifoldMap' ('Endo' '.' f) ('Endo' '.' g) t) z@+bifoldableLaws :: forall f.+  ( Bifoldable f+  , forall x y. (Eq x, Eq y) => Eq (f x y)+  , forall x y. (Show x, Show y) => Show (f x y)+  ) => (forall x y. Gen x -> Gen y -> Gen (f x y)) -> Laws+bifoldableLaws gen = Laws "Bifoldable"+  [ ("Identity", bifoldableIdentity gen)+  , ("FoldMap", bifoldableFoldMap gen)+  , ("Foldr", bifoldableFoldr gen)+  ]++-- | Tests the following 'Bifoldable' / 'Bifunctor' laws:+--+-- [__Composition__]: @'bifoldMap' f g@ ≡ @'bifold' '.' 'bimap' f g@+-- [__FoldMap__]: @'bifoldMap' f g '.' 'bimap' h i@ ≡ @'bifoldMap' (f '.' h) (g '.' i)@+bifoldableFunctorLaws :: forall f.+  ( Bifoldable f, Bifunctor f+  , forall x y. (Eq x, Eq y) => Eq (f x y)+  , forall x y. (Show x, Show y) => Show (f x y)+  ) => (forall x y. Gen x -> Gen y -> Gen (f x y)) -> Laws+bifoldableFunctorLaws gen = Laws "Bifoldable/Bifunctor"+  [ ("Composition", bifoldableFunctorComposition gen)+  , ("FoldMap", bifoldableFunctorFoldMap gen)+  ]++type BifoldableProp f =+  ( Bifoldable f+  , forall x y. (Eq x, Eq y) => Eq (f x y)+  , forall x y. (Show x, Show y) => Show (f x y)+  ) => (forall x y. Gen x -> Gen y -> Gen (f x y)) -> Property++bifoldableIdentity :: forall f. BifoldableProp f+bifoldableIdentity fgen = property $ do+  x <- forAll $ fgen genSmallSum genSmallSum+  let lhs = bifold x+  let rhs = bifoldMap id id x+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Identity", lawContextLawBody = "bifold" `congruency` "bifoldMap id id"+        , lawContextTcName = "Bifoldable", lawContextTcProp =+             let showX = show x;+             in lawWhere+                 [ "bimap id id x" `congruency` "x, where"+                 , "x = " ++ showX+                 ]+        , lawContextReduced = reduced lhs rhs +        } +  heqCtx lhs rhs ctx+        +bifoldableFoldMap :: forall f. BifoldableProp f+bifoldableFoldMap fgen = property $ do+  x <- forAll $ fgen genSmallInteger genSmallInteger+  let f = Sum; g = Sum . (+1)+  let lhs = (bifoldMap f g x)+  let rhs = (bifoldr (mappend . f) (mappend . g) mempty x)+  let ctx = contextualise $ LawContext+        { lawContextLawName = "FoldMap", lawContextLawBody = "bifoldMap f g" `congruency` "bifoldr (mappend . f) (mappend . g) mempty"+        , lawContextTcName = "Bifoldable", lawContextTcProp =+             let showX = show x;+             in lawWhere+                 [ "bifoldMap f g x" `congruency` "bifoldr (mappend . f) (mappend . g) mempty x, where"+                 , "f = \\x -> Sum x"+                 , "g = \\x -> Sum (x + 1)"+                 , "x = " ++ showX+                 ]+        , lawContextReduced = reduced lhs rhs +        } +  heqCtx lhs rhs ctx++bifoldableFoldr :: forall f. BifoldableProp f+bifoldableFoldr fgen = property $ do+  x <- forAll $ fgen genSmallInteger genSmallInteger+  f' <- forAll genLinearEquationTwo+  g' <- forAll genLinearEquationTwo+  let f = runLinearEquationTwo f'+  let g = runLinearEquationTwo g'+  let z0 = 0+  let lhs = (bifoldr f g z0 x)+  let rhs = (appEndo (bifoldMap (Endo . f) (Endo . g) x) z0)+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Foldr", lawContextLawBody = "bifoldr f g z t" `congruency` "appEndo (bifoldMap (Endo . f) (Endo . g) t) z"+        , lawContextTcName = "Bifoldable", lawContextTcProp =+            let showX = show x; showF = show f'; showG = show g'; showZ = show z0;+            in lawWhere+              [ "bifoldr f g z t" `congruency` "appEndo (bifoldMap (Endo . f) (Endo . g) t z, where"+              , "f = " ++ showF+              , "g = " ++ showG+              , "t = " ++ showX+              , "z = " ++ showZ+              ]+        , lawContextReduced = reduced lhs rhs +        }+  heqCtx lhs rhs ctx ++type BifoldableFunctorProp f =+  ( Bifoldable f, Bifunctor f+  , forall x y. (Eq x, Eq y) => Eq (f x y)+  , forall x y. (Show x, Show y) => Show (f x y)+  ) => (forall x y. Gen x -> Gen y -> Gen (f x y)) -> Property++bifoldableFunctorComposition :: forall f. BifoldableFunctorProp f+bifoldableFunctorComposition fgen = property $ do+  x <- forAll $ fgen genSmallSum genSmallSum+  let f = Product; g = Product . (+1)+  let lhs = bifoldMap f g x+  let rhs = bifold (bimap f g x)+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Composition", lawContextLawBody = "bifoldMap f g" `congruency` "bifold . bimap f g"+        , lawContextTcName = "Bifoldable/Bifunctor", lawContextTcProp =+            let showX = show x;+            in lawWhere+              [ "bifoldMap f g x" `congruency` "bifold . bimap f g $ x"+              , "f = \\x -> Product x"+              , "g = \\x -> Product (x + 1)"+              , "x = " ++ showX+              ]+        , lawContextReduced = reduced lhs rhs +        }+  heqCtx lhs rhs ctx ++bifoldableFunctorFoldMap :: forall f. BifoldableFunctorProp f+bifoldableFunctorFoldMap fgen = property $ do+  x <- forAll $ fgen genSmallSum genSmallSum+  let h (Sum s) = s * s + 3; showH = "\\(Sum s) -> s * s + 3"+  let i (Sum s) = s + s - 7; showI = "\\(Sum s) -> s + s - 7"+  let f = Sum; showF = "\\x -> Sum x"; g = Sum . (+1); showG = "\\x -> Sum (x + 1)"+  let lhs = bifoldMap f g (bimap h i x)+  let rhs = bifoldMap (f . h) (g . i) x+  let ctx = contextualise $ LawContext+        { lawContextLawName = "FoldMap", lawContextLawBody = "bifoldMap f g . bimap h i" `congruency` "bifoldMap (f . h) (g . i)"+        , lawContextTcName = "Bifoldable/Bifunctor", lawContextTcProp =+            let showX = show x;+            in lawWhere+              [ "bifoldMap f g . bimap h i $ x" `congruency` "bifoldMap (f . h) (g . i) $ x, where"+              , "f = " ++ showF+              , "g = " ++ showG+              , "h = " ++ showH+              , "i = " ++ showI+              , "x = " ++ showX+              ]+        , lawContextReduced = reduced lhs rhs +        }+  heqCtx lhs rhs ctx+
+ src/Hedgehog/Classes/Bifunctor.hs view
@@ -0,0 +1,102 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE QuantifiedConstraints #-}++module Hedgehog.Classes.Bifunctor (bifunctorLaws) where++import Hedgehog+import Hedgehog.Classes.Common++import Data.Bifunctor (Bifunctor(..))++-- | Tests the following 'Bifunctor' laws:+--+-- [__Identity__]: @'bimap' 'id' 'id'@ ≡ @'id'@+-- [__First Identity__]: @'first' 'id'@ ≡ @'id'@+-- [__Second Identity__]: @'second' 'id'@ ≡ @'id'@+-- [__Composition__]: @'bimap' 'id' 'id'@ ≡ @'first' 'id' '.' 'second' 'id'@+bifunctorLaws :: forall f.+  ( Bifunctor f+  , forall x y. (Eq x, Eq y) => Eq (f x y)+  , forall x y. (Show x, Show y) => Show (f x y)+  ) => (forall x y. Gen x -> Gen y -> Gen (f x y)) -> Laws+bifunctorLaws gen = Laws "Bifunctor"+  [ ("Identity", bifunctorIdentity gen)+  , ("First Identity", bifunctorFirstIdentity gen)+  , ("Second Identity", bifunctorSecondIdentity gen)+  , ("Composition", bifunctorComposition gen) +  ]++type BifunctorProp f =+  ( Bifunctor f+  , forall x y. (Eq x, Eq y) => Eq (f x y)+  , forall x y. (Show x, Show y) => Show (f x y)+  ) => (forall x y. Gen x -> Gen y -> Gen (f x y)) -> Property++bifunctorIdentity :: forall f. BifunctorProp f+bifunctorIdentity fgen = property $ do+  x <- forAll $ fgen genSmallInteger genSmallInteger+  let lhs = bimap id id x+  let rhs = x+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Identity", lawContextLawBody = "bimap id id" `congruency` "id"+        , lawContextTcName = "Bifunctor", lawContextTcProp =+             let showX = show x;+             in lawWhere+                 [ "bimap id id x" `congruency` "x, where"+                 , "x = " ++ showX+                 ]+        , lawContextReduced = reduced lhs rhs +        } +  heqCtx2 lhs rhs ctx ++bifunctorFirstIdentity :: forall f. BifunctorProp f+bifunctorFirstIdentity fgen = property $ do+  x <- forAll $ fgen genSmallInteger genSmallInteger+  let lhs = first id x+  let rhs = x+  let ctx = contextualise $ LawContext+        { lawContextLawName = "First Identity", lawContextLawBody = "first id" `congruency` "id"+        , lawContextTcName = "Bifunctor", lawContextTcProp =+            let showX = show x;+            in lawWhere+              [ "first id x" `congruency` "x, where"+              , "x = " ++ showX+              ]+        , lawContextReduced = reduced lhs rhs +        }+  heqCtx2 lhs rhs ctx++bifunctorSecondIdentity :: forall f. BifunctorProp f+bifunctorSecondIdentity fgen = property $ do+  x <- forAll $ fgen genSmallInteger genSmallInteger+  let lhs = second id x+  let rhs = x+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Second Identity", lawContextLawBody = "second id" `congruency` "id"+        , lawContextTcName = "Bifunctor", lawContextTcProp =+            let showX = show x;+            in lawWhere+              [ "second id x" `congruency` "x, where"+              , "x = " ++ showX+              ]+        , lawContextReduced = reduced lhs rhs +        }+  heqCtx2 lhs rhs ctx++bifunctorComposition :: forall f. BifunctorProp f+bifunctorComposition fgen = property $ do+  z <- forAll $ fgen genSmallInteger genSmallInteger+  let lhs = bimap id id z+  let rhs = (first id . second id) z+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Composition", lawContextLawBody = "bimap id id" `congruency` "first id . second id"+        , lawContextTcName = "Bifunctor", lawContextTcProp =+            let showX = show z;+            in lawWhere+              [ "bimap id id x" `congruency` "first id . second id $ x, where"+              , "x = " ++ showX+              ]+        , lawContextReduced = reduced lhs rhs +        }       +  heqCtx2 lhs rhs ctx
+ src/Hedgehog/Classes/Bitraversable.hs view
@@ -0,0 +1,93 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE QuantifiedConstraints #-}++module Hedgehog.Classes.Bitraversable (bitraversableLaws) where++import Hedgehog+import Hedgehog.Classes.Common++import Data.Bitraversable (Bitraversable(..))+import Data.Functor.Compose (Compose(..))+import Data.Functor.Identity (Identity(..))++import qualified Data.Set as S+import qualified Control.Monad.Trans.Writer.Lazy as WL++-- | Tests the following 'Bitraversable' laws:+--+-- [__Naturality__]: @'bitraverse' (t '.' f) (t '.' g)@ ≡ @t '.' 'bitraverse' f g, for every applicative transformation t@+-- [__Identity__]: @'bitraverse' 'Identity' 'Identity'@ ≡ @'Identity'@+-- [__Composition__]: @'Compose' '.' 'fmap' ('bitraverse' g1 g2) '.' 'bitraverse' f1 f2@ ≡ @'bitraverse' ('Compose' '.' 'fmap' g1 '.' f1) ('Compose' '.' 'fmap' g2 '.' f2)@+bitraversableLaws :: forall f.+  ( Bitraversable f+  , forall x y. (Eq x, Eq y) => Eq (f x y)+  , forall x y. (Show x, Show y) => Show (f x y)+  ) => (forall x y. Gen x -> Gen y -> Gen (f x y)) -> Laws+bitraversableLaws gen = Laws "Bitraversable"+  [ ("Naturality", bitraversableNaturality gen)+  , ("Identity", bitraversableIdentity gen)+  , ("Composition", bitraversableComposition gen) +  ]++type BitraversableProp f =+  ( Bitraversable f+  , forall x y. (Eq x, Eq y) => Eq (f x y)+  , forall x y. (Show x, Show y) => Show (f x y)+  ) => (forall x y. Gen x -> Gen y -> Gen (f x y)) -> Property++bitraversableNaturality :: forall f. BitraversableProp f+bitraversableNaturality fgen = property $ do+  x <- forAll $ fgen genSmallInteger genSmallInteger+  let t = apTrans; f = func4; g = func4+  let lhs = bitraverse (t . f) (t . g) x+  let rhs = t (bitraverse f g x)+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Naturality", lawContextLawBody = "bitraverse (t . f) (t . g)" `congruency` "t . bitraverse f g, for every applicative transformation t"+        , lawContextTcName = "Bitraversable", lawContextTcProp =+            let showX = show x;+            in lawWhere+                 [ "bitraverse (t . f) (t . g) $ x" `congruency` "t . bitraverse f g $ x, for every applicative transformation t, where"+                 , "x = " ++ showX+                 ]+        , lawContextReduced = reduced lhs rhs +        }+  heqCtx1 lhs rhs ctx  ++bitraversableIdentity :: forall f. BitraversableProp f+bitraversableIdentity fgen = property $ do+  x <- forAll $ fgen genSmallInteger genSmallInteger+  let lhs = bitraverse Identity Identity x+  let rhs = Identity x+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Identity", lawContextLawBody = "bitraverse Identity Identity" `congruency` "Identity"+        , lawContextTcName = "Bitraversable", lawContextTcProp =+            let showX = show x;+            in lawWhere+                 [ "bitraverse Identity Identity x" `congruency` "Identity x, where"+                 , "x = " ++ showX+                 ]+        , lawContextReduced = reduced lhs rhs +        }+  heqCtx1 lhs rhs ctx  +  +bitraversableComposition :: forall f. BitraversableProp f+bitraversableComposition fgen = property $ do+  x <- forAll $ fgen genSmallInteger genSmallInteger+  let f1 = func6; f2 = func5; g1 = func4; g2 = func4+  let lhs :: Compose Triple (Compose Triple (WL.Writer (S.Set Integer))) (f Integer Integer)+      lhs = Compose . fmap (bitraverse g1 g2) . bitraverse f1 f2 $ x+      +  let rhs :: Compose Triple (Compose Triple (WL.Writer (S.Set Integer))) (f Integer Integer)+      rhs = bitraverse (Compose . fmap g1 . f1) (Compose . fmap g2 . f2) x+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Composition", lawContextLawBody = "Compose . fmap (bitraverse g1 g2) . bitraverse f1 f2" `congruency` "bitraverse (Compose . fmap g1 . f1) (Compose . fmap g2 . f2)"+        , lawContextTcName = "Bitraversable", lawContextTcProp =+            let showX = show x;  +            in lawWhere+                 [ "Compose . fmap (bitraverse g1 g2) . bitraverse f1 f2 $ x" `congruency` "bitraverse (Compose . fmap g1 . f1) (Compose . fmap g2 . f2) $ x, where"+                 , "x = " ++ showX+                 ]+        , lawContextReduced = reduced lhs rhs +        }+  heqCtx1 lhs rhs ctx
+ src/Hedgehog/Classes/Bits.hs view
@@ -0,0 +1,281 @@+{-# LANGUAGE ScopedTypeVariables #-}++module Hedgehog.Classes.Bits (bitsLaws) where++import Data.Bits+import Hedgehog+import Hedgehog.Classes.Common++import qualified Hedgehog.Gen as Gen+import qualified Hedgehog.Range as Range++-- | Tests the following 'Bits' laws:+--+-- [__Conjunction Idempotence__]: @n '.&.' n@ ≡ @n@+-- [__Disjunction Idempotence__]: @n '.|.' n@ ≡ @n@+-- [__Double Complement__]: @'complement' '.' 'complement'@ ≡ @id@+-- [__Set Bit__]: @'setBit' n i ≡ n '.|.' 'bit' i@+-- [__Clear Bit__]: @'clearBit' n i@ ≡ @n '.&.' 'complement' ('bit' i)@+-- [__Complement Bit__]: @'complement' n i@ ≡ @'xor' n ('bit' i)@+-- [__Clear Zero__]: @'clearBit' 'zeroBits' i@ ≡ @'zeroBits'@+-- [__Set Zero__]: @'setBit' 'zeroBits' i@ ≡ @'zeroBits'@+-- [__Test Zero__]: @'testBit' 'zeroBits' i@ ≡ @'False'@+-- [__Pop Zero__]: @'popCount' 'zeroBits'@ ≡ @0@+-- [__Count Leading Zeros of Zero__]: @'countLeadingZeros' 'zeroBits'@ ≡ @'finiteBitSize' ('undefined' :: a)@+-- [__Count Trailing Zeros of Zero__]: @'countTrailingZeros' 'zeroBits'@ ≡ @'finiteBitSize' ('undefined' :: a)@+bitsLaws :: (FiniteBits a, Show a) => Gen a -> Laws+bitsLaws gen = Laws "Bits"+  [ ("Conjunction Idempotence", bitsConjunctionIdempotence gen)+  , ("Disjunction Idempotence", bitsDisjunctionIdempotence gen)+  , ("Double Complement", bitsDoubleComplement gen) +  , ("Set Bit", bitsSetBit gen) +  , ("Clear Bit", bitsClearBit gen)+  , ("Complement Bit", bitsComplementBit gen)+  , ("Clear Zero", bitsClearZero gen)+  , ("Set Zero", bitsSetZero gen)+  , ("Test Zero", bitsTestZero gen)+  , ("Pop Zero", bitsPopZero gen)+  , ("Count Leading Zeros of Zero", bitsCountLeadingZeros gen)+  , ("Count Trailing Zeros of Zero", bitsCountTrailingZeros gen)+  ]++newtype BitIndex a = BitIndex Int+  deriving (Show)++genBitIndex :: forall a. FiniteBits a => Gen (BitIndex a)+genBitIndex = let n = finiteBitSize (undefined :: a) in if n > 0+  then fmap BitIndex (Gen.integral $ Range.linear 0 (n - 1))+  else pure (BitIndex 0)++bitsConjunctionIdempotence :: forall a. (Bits a, Show a) => Gen a -> Property+bitsConjunctionIdempotence gen = property $ do+  n <- forAll gen+  let lhs = n .&. n; rhs = n; +  let ctx = contextualise $ LawContext+        { lawContextLawName = "Conjunction Idempotence"+        , lawContextLawBody = "n .&. n" `congruency` "n"+        , lawContextTcName = "Bits"+        , lawContextTcProp =+            let showN = show n;+            in lawWhere [ "n .&. n" `congruency` "n, where", "n = " ++ showN ]+        , lawContextReduced = reduced lhs rhs +        }+  heqCtx lhs rhs ctx++bitsDisjunctionIdempotence :: forall a. (Bits a, Show a) => Gen a -> Property+bitsDisjunctionIdempotence gen = property $ do+  n <- forAll gen+  let lhs = n .|. n; rhs = n; +  let ctx = contextualise $ LawContext+        { lawContextLawName = "Disjunction Idempotence"+        , lawContextLawBody = "n .|. n" `congruency` "n"+        , lawContextTcName = "Bits"+        , lawContextTcProp =+            let showN = show n+            in lawWhere [ "n .|. n" `congruency` "n, where", "n = " ++ showN ]+        , lawContextReduced = reduced lhs rhs +        }+  heqCtx lhs rhs ctx++bitsDoubleComplement :: forall a. (Bits a, Show a) => Gen a -> Property+bitsDoubleComplement gen = property $ do+  n <- forAll gen+  let lhs = complement (complement n); rhs = n;+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Double Complement"+        , lawContextLawBody = "complement . complement" `congruency` "id"+        , lawContextTcName = "Bits"+        , lawContextTcProp =+            let showN = show n+            in lawWhere [ "complement . complement $ n" `congruency` "id n, where", "n = " ++ showN ]+        , lawContextReduced = reduced lhs rhs +        }+  +  heqCtx lhs rhs ctx++bitsSetBit :: forall a. (FiniteBits a, Show a) => Gen a -> Property+bitsSetBit gen = property $ do+  n <- forAll gen+  (BitIndex i) :: BitIndex a <- forAll genBitIndex+  let lhs = setBit n i; rhs = n .|. bit i;+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Set Bit"+        , lawContextLawBody = "setBit n i" `congruency` "n .|. bit i"+        , lawContextTcName = "Bits"+        , lawContextTcProp =+            let showN = show n+                showI = show i+            in lawWhere+                 [ "setBit n i" `congruency` "n .|. bit i, where"+                 , "n = " ++ showN+                 , "i = " ++ showI+                 ]+        , lawContextReduced = reduced lhs rhs +        } +  heqCtx lhs rhs ctx++bitsClearBit :: forall a. (FiniteBits a, Show a) => Gen a -> Property+bitsClearBit gen = property $ do+  n <- forAll gen+  (BitIndex i) :: BitIndex a <- forAll genBitIndex+  let lhs = clearBit n i; rhs = n .&. complement (bit i)+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Clear Bit"+        , lawContextLawBody = "clearBit n i" `congruency` "n .&. complement (bit i)"+        , lawContextTcName = "Bits"+        , lawContextTcProp =+            let showN = show n+                showI = show i+            in lawWhere+                 [ "clearBit n i" `congruency` "n .&. complement (bit i), where"+                 , "n = " ++ showN+                 , "i = " ++ showI+                 ]+        , lawContextReduced = reduced lhs rhs +        }+  heqCtx lhs rhs ctx++bitsComplementBit :: forall a. (FiniteBits a, Show a) => Gen a -> Property+bitsComplementBit gen = property $ do+  n <- forAll gen+  (BitIndex i) :: BitIndex a <- forAll genBitIndex+  let lhs = complementBit n i; rhs = xor n (bit i);+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Complement Bit"+        , lawContextLawBody = "complement n i" `congruency` "xor n (bit i)"+        , lawContextTcName = "Bits"+        , lawContextTcProp =+            let showN = show n+                showI = show i+            in lawWhere+                 [ "complement n i" `congruency` "xor n (bit i), where"+                 , "n = " ++ showN+                 , "i = " ++ showI+                 ]+        , lawContextReduced = reduced lhs rhs +        } +  heqCtx lhs rhs ctx++bitsClearZero :: forall a. (FiniteBits a, Show a) => Gen a -> Property+bitsClearZero _ = property $ do+  (BitIndex i) :: BitIndex a <- forAll genBitIndex+  let z = zeroBits :: a+  let lhs = clearBit z i; rhs = z+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Clear Zero"+        , lawContextLawBody = "clearBit zeroBits i" `congruency` "zeroBits"+        , lawContextTcName = "Bits"+        , lawContextTcProp =+            let showZ = show z+                showI = show i+            in lawWhere+                 [ "clearBit zeroBits i" `congruency` "zeroBits, where"+                 , "zerBits = " ++ showZ+                 , "i = " ++ showI+                 ]+        , lawContextReduced = reduced lhs rhs +        }+  heqCtx lhs rhs ctx++bitsSetZero :: forall a. (FiniteBits a, Show a) => Gen a -> Property+bitsSetZero _ = property $ do+  (BitIndex i) :: BitIndex a <- forAll genBitIndex+  let z = zeroBits :: a+  let lhs = setBit z i; rhs = bit i;+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Set Zero"+        , lawContextLawBody = "setBit zeroBits i" `congruency` "zeroBits"+        , lawContextTcName = "Bits"+        , lawContextTcProp =+            let showZ = show z+                showI = show i+            in lawWhere+              [ "setBit zeroBits i" `congruency` "zeroBits, where"+              , "zeroBits = " ++ showZ+              , "i = " ++ showI+              ]+        , lawContextReduced = reduced lhs rhs +        }+  heqCtx lhs rhs ctx++bitsTestZero :: forall a. (FiniteBits a, Show a) => Gen a -> Property+bitsTestZero _ = property $ do+  (BitIndex i) :: BitIndex a <- forAll genBitIndex+  let z = zeroBits :: a+  let lhs = testBit z i; rhs = False;+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Test Zero"+        , lawContextLawBody = "testBit zeroBits i" `congruency` "False"+        , lawContextTcName = "Bits"+        , lawContextTcProp =+            let showZ = show z+                showI = show i+            in lawWhere+              [ "testBit zeroBits i" `congruency` "False, where"+              , "zeroBits = " ++ showZ+              , "i = " ++ showI+              ]+        , lawContextReduced = reduced lhs rhs +        }+  heqCtx lhs rhs ctx  ++bitsPopZero :: forall a. (FiniteBits a, Show a) => Gen a -> Property+bitsPopZero _ = property $ do+  let z = zeroBits :: a+  let lhs = popCount z; rhs = 0;+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Pop Zero"+        , lawContextLawBody = "popCount zeroBits" `congruency` "0"+        , lawContextTcName = "Bits"+        , lawContextTcProp =+            let showZ = show z+            in lawWhere+              [ "popCount zeroBits" `congruency` "0, where"+              , "zeroBits = " ++ showZ+              ]+        , lawContextReduced = reduced lhs rhs +        } +  heqCtx lhs rhs ctx++bitsCountLeadingZeros :: forall a. (FiniteBits a, Show a) => Gen a -> Property+bitsCountLeadingZeros _ = property $ do+  let z = zeroBits :: a+  let f = finiteBitSize (undefined :: a)+  let lhs = countLeadingZeros z; rhs = f;+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Count Leading Zeros of Zero"+        , lawContextLawBody = "countLeadingZeros zeroBits" `congruency` "finiteBitSize (undefined :: a)"+        , lawContextTcName = "Bits"+        , lawContextTcProp =+            let showZ = show z+                showF = show f+            in lawWhere+              [ "countLeadingZeros zeroBits" `congruency` "finiteBitSize (undefined :: a), where"+              , "zeroBits = " ++ showZ+              , "finiteBitSize = " ++ showF+              ]+        , lawContextReduced = reduced lhs rhs +        } +  heqCtx lhs rhs ctx++bitsCountTrailingZeros :: forall a. (FiniteBits a, Show a) => Gen a -> Property+bitsCountTrailingZeros _ = property $ do+  let z = zeroBits :: a+  let f = finiteBitSize (undefined :: a)+  let lhs = countTrailingZeros z; rhs = f;+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Count Trailing Zeros of Zero"+        , lawContextLawBody = "countTrailingZeros zeroBits" `congruency` "finiteBitSize (undefined :: a)"+        , lawContextTcName = "Bits"+        , lawContextTcProp =+            let showZ = show z+                showF = show f+            in lawWhere+              [ "countTrailingZeros zeroBits" `congruency` "finiteBitSize (undefined :: a), where"+              , "zeroBits = " ++ showZ+              , "finiteBitSize = " ++ showF+              ]           +        , lawContextReduced = reduced lhs rhs +        }+  heqCtx lhs rhs ctx+
+ src/Hedgehog/Classes/Category.hs view
@@ -0,0 +1,78 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE QuantifiedConstraints #-}++module Hedgehog.Classes.Category (categoryLaws, commutativeCategoryLaws) where++import Hedgehog+import Hedgehog.Classes.Common++import Control.Category(Category(..))+import Prelude hiding (id, (.))++-- | Tests the following 'Category' laws:+--+-- [__Left Identity__]: @'id' '.' f@ ≡ @f@+-- [__Right Identity__]: @f '.' 'id'@ ≡ @f@+-- [__Associativity__]: @f '.' (g '.' h)@ ≡ @(f '.' g) '.' h@+categoryLaws :: forall f.+  ( Category f+  , forall x y. (Eq x, Eq y) => Eq (f x y)+  , forall x y. (Show x, Show y) => Show (f x y)+  ) => (forall x y. Gen x -> Gen y -> Gen (f x y)) -> Laws+categoryLaws gen = Laws "Category"+  [ ("Left Identity", categoryLeftIdentity gen)+  , ("Right Identity", categoryRightIdentity gen)+  , ("Associativity", categoryAssociativity gen)+  ]++-- | Tests the following 'Category' laws:+--+-- [__Commutativity__]: @f '.' g@ ≡ @g '.' f@+commutativeCategoryLaws :: forall f.+  ( Category f+  , forall x y. (Eq x, Eq y) => Eq (f x y)+  , forall x y. (Show x, Show y) => Show (f x y)+  ) => (forall x y. Gen x -> Gen y -> Gen (f x y)) -> Laws+commutativeCategoryLaws gen = Laws "Commutative Category"+  [ ("Commutativity", categoryCommutativity gen)+  ]++categoryRightIdentity :: forall f.+  ( Category f+  , forall x y. (Eq x, Eq y) => Eq (f x y)+  , forall x y. (Show x, Show y) => Show (f x y)+  ) => (forall x y. Gen x -> Gen y -> Gen (f x y)) -> Property+categoryRightIdentity fgen = property $ do+  x <- forAll $ fgen genSmallInteger genSmallInteger+  (x . id) `heq2` x++categoryLeftIdentity :: forall f.+  ( Category f+  , forall x y. (Eq x, Eq y) => Eq (f x y)+  , forall x y. (Show x, Show y) => Show (f x y)+  ) => (forall x y. Gen x -> Gen y -> Gen (f x y)) -> Property+categoryLeftIdentity fgen = property $ do+  x <- forAll $ fgen genSmallInteger genSmallInteger+  (id . x) `heq2` x++categoryAssociativity :: forall f.+  ( Category f+  , forall x y. (Eq x, Eq y) => Eq (f x y)+  , forall x y. (Show x, Show y) => Show (f x y)+  ) => (forall x y. Gen x -> Gen y -> Gen (f x y)) -> Property+categoryAssociativity fgen = property $ do+  f <- forAll $ fgen genSmallInteger genSmallInteger+  g <- forAll $ fgen genSmallInteger genSmallInteger +  h <- forAll $ fgen genSmallInteger genSmallInteger +  (f . (g . h)) `heq2` ((f . g) . h)++categoryCommutativity :: forall f.+  ( Category f+  , forall x y. (Eq x, Eq y) => Eq (f x y)+  , forall x y. (Show x, Show y) => Show (f x y)+  ) => (forall x y. Gen x -> Gen y -> Gen (f x y)) -> Property+categoryCommutativity fgen = property $ do+  f <- forAll $ fgen genSmallInteger genSmallInteger+  g <- forAll $ fgen genSmallInteger genSmallInteger+  (f . g) `heq2` (g . f)
+ src/Hedgehog/Classes/Common.hs view
@@ -0,0 +1,13 @@+module Hedgehog.Classes.Common+  ( module Common +  ) where++import Hedgehog.Classes.Common.ApTrans  as Common+import Hedgehog.Classes.Common.Bottom   as Common+import Hedgehog.Classes.Common.Compat   as Common+import Hedgehog.Classes.Common.Equation as Common+import Hedgehog.Classes.Common.Func     as Common+import Hedgehog.Classes.Common.Gen      as Common+import Hedgehog.Classes.Common.IO       as Common+import Hedgehog.Classes.Common.Laws     as Common+import Hedgehog.Classes.Common.Property as Common
+ src/Hedgehog/Classes/Common/ApTrans.hs view
@@ -0,0 +1,25 @@+module Hedgehog.Classes.Common.ApTrans+  ( apTrans+  , toSpecialApplicative+  ) where++import Data.Tuple (swap)+import Data.Functor.Compose+import qualified Data.Set as S+import qualified Control.Monad.Trans.Writer.Lazy as WL++import Hedgehog.Classes.Common.Func++-- Reverse the list and accumulate the writers. We+-- cannot use Sum or Product or else it won't actually+-- be a valid applicative transformation.+apTrans ::+     Compose Triple (WL.Writer (S.Set Integer)) a+  -> Compose (WL.Writer (S.Set Integer)) Triple a+apTrans (Compose xs) = Compose (sequenceA (reverseTriple xs))++toSpecialApplicative ::+     Compose Triple ((,) (S.Set Integer)) Integer+  -> Compose Triple (WL.Writer (S.Set Integer)) Integer+toSpecialApplicative (Compose (Triple a b c)) =+  Compose (Triple (WL.writer (swap a)) (WL.writer (swap b)) (WL.writer (swap c)))
+ src/Hedgehog/Classes/Common/Bottom.hs view
@@ -0,0 +1,22 @@+{-# LANGUAGE LambdaCase #-}++module Hedgehog.Classes.Common.Bottom+  ( Bottom(..), genBottom+  ) where++import Hedgehog+import qualified Hedgehog.Gen as Gen+ +data Bottom a = BottomUndefined | BottomValue a+  deriving (Eq)++instance Show a => Show (Bottom a) where+  show = \case+    BottomUndefined -> "undefined"+    BottomValue a   -> show a++genBottom :: Gen a -> Gen (Bottom a)+genBottom = fmap maybeToBottom . Gen.maybe++maybeToBottom :: Maybe a -> Bottom a+maybeToBottom = \case { Nothing -> BottomUndefined; Just a -> BottomValue a }
+ src/Hedgehog/Classes/Common/Compat.hs view
@@ -0,0 +1,79 @@+{-# LANGUAGE CPP #-}++#if HAVE_QUANTIFIED_CONSTRAINTS+{-# LANGUAGE QuantifiedConstraints #-}+#endif++module Hedgehog.Classes.Common.Compat+  ( readMaybe+  , eq +  , eq1+  , eq2++  , show1+  , show2++  , neq+  , neq1+  , neq2+  ) where++#if HAVE_QUANTIFIED_CONSTRAINTS == 0+import qualified Data.Functor.Classes as C+#endif++import Text.Read (readMaybe)++eq :: Eq a => a -> a -> Bool+eq = (==)++neq :: Eq a => a -> a -> Bool+neq = (/=)++#if HAVE_QUANTIFIED_CONSTRAINTS+eq1 :: (Eq a, forall x. Eq x => Eq (f x)) => f a -> f a -> Bool+eq1 = (==)+#else+eq1 :: (C.Eq1 f, Eq a) => f a -> f a -> Bool+eq1 = C.eq1+#endif++#if HAVE_QUANTIFIED_CONSTRAINTS+neq1 :: (Eq a, forall x. Eq x => Eq (f x)) => f a -> f a -> Bool+neq1 = (/=)+#else+neq1 :: (C.Eq1 f, Eq a) => f a -> f a -> Bool+neq1 x y = not $ C.eq1 x y +#endif++#if HAVE_QUANTIFIED_CONSTRAINTS+eq2 :: (Eq a, Eq b, forall x y. (Eq x, Eq y) => Eq (f x y)) => f a b -> f a b -> Bool+eq2 = (==)+#else+eq2 :: (C.Eq2 f, Eq a, Eq b) => f a b -> f a b -> Bool+eq2 = C.eq2+#endif++#if HAVE_QUANTIFIED_CONSTRAINTS+neq2 :: (Eq a, Eq b, forall x y. (Eq x, Eq y) => Eq (f x y)) => f a b -> f a b -> Bool+neq2 = (/=)+#else+neq2 :: (C.Eq2 f, Eq a, Eq b) => f a b -> f a b -> Bool+neq2 x y = not $ C.eq2 x y+#endif++#if HAVE_QUANTIFIED_CONSTRAINTS+show1 :: (Show a, forall x. (Show x) => Show (f x)) => f a -> String+show1 = Prelude.show+#else+show1 :: (C.Show1 f, Show a) => f a -> String+show1 x = C.showsPrec1 0 x ""+#endif++#if HAVE_QUANTIFIED_CONSTRAINTS+show2 :: (Show a, Show b, forall x y. (Show x, Show y) => Show (f x y)) => f a b -> String+show2 = Prelude.show+#else+show2 :: (C.Show2 f, Show a, Show b) => f a b -> String+show2 x = C.showsPrec2 0 x ""+#endif
+ src/Hedgehog/Classes/Common/Equation.hs view
@@ -0,0 +1,115 @@+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE QuantifiedConstraints #-}+{-# LANGUAGE UndecidableInstances #-}++module Hedgehog.Classes.Common.Equation+  ( LinearEquation(..), runLinearEquation, genLinearEquation+  , LinearEquationTwo(..), runLinearEquationTwo, genLinearEquationTwo+  , LinearEquationM(..), runLinearEquationM, genLinearEquationM+  , QuadraticEquation(..), runQuadraticEquation, genQuadraticEquation+  , CubicEquation(..), runCubicEquation, genCubicEquation++  ) where++import Hedgehog+import Hedgehog.Classes.Common.Gen+import qualified Hedgehog.Gen as Gen+import qualified Hedgehog.Range as Range+import qualified Data.List as List++import Data.Monoid (Endo(..))++data QuadraticEquation = QuadraticEquation+  { _quadraticEquationQuadratic :: Integer+  , _quadraticEquationLinear :: Integer+  , _quadraticEquationConstant :: Integer+  }+  deriving (Eq)++-- This show instance does not actually provide a way+-- to create an equation. Instead, it makes it look+-- like a lambda.+instance Show QuadraticEquation where+  show (QuadraticEquation a b c) = "\\x -> " ++ show a ++ " * x ^ 2 + " ++ show b ++ " * x + " ++ show c++genQuadraticEquation :: Gen QuadraticEquation+genQuadraticEquation = do+  a <- Gen.integral (Range.linear 0 15)+  b <- Gen.integral (Range.linear 0 15)+  c <- Gen.integral (Range.linear 0 15)+  pure (QuadraticEquation a b c)++runQuadraticEquation :: QuadraticEquation -> Integer -> Integer+runQuadraticEquation (QuadraticEquation a b c) x = a * x ^ (2 :: Integer) + b * x + c++data LinearEquation = LinearEquation+  { _linearEquationLinear :: Integer+  , _linearEquationConstant :: Integer+  }+  deriving (Eq)++instance Show LinearEquation where+  showsPrec _ (LinearEquation a b) = shows a . showString " * x + " . shows b+  showList xs = appEndo+    $ mconcat+    $  [Endo (showChar '[')]+    ++ List.intersperse (Endo (showChar ',')) (map (Endo . showsPrec 0) xs)+    ++ [Endo (showChar ']')]++runLinearEquation :: LinearEquation -> Integer -> Integer+runLinearEquation (LinearEquation a b) x = a * x + b++genLinearEquation :: Gen LinearEquation+genLinearEquation = LinearEquation <$> genSmallInteger <*> genSmallInteger++data LinearEquationM m = LinearEquationM (m LinearEquation) (m LinearEquation)++deriving instance (forall x. Eq x => Eq (m x)) => Eq (LinearEquationM m)++instance (forall x. Show x => Show (m x)) => Show (LinearEquationM m) where+  show (LinearEquationM a b) = (\f -> f "")+    $ showString "\\x -> if odd x then "+    . showsPrec 0 a+    . showString " else "+    . showsPrec 0 b++runLinearEquationM :: Functor m => LinearEquationM m -> Integer -> m Integer+runLinearEquationM (LinearEquationM e1 e2) i = if odd i+  then fmap (flip runLinearEquation i) e1+  else fmap (flip runLinearEquation i) e2++genLinearEquationM :: Applicative m => Gen (LinearEquationM m)+genLinearEquationM = LinearEquationM <$> (pure <$> genLinearEquation) <*> (pure <$> genLinearEquation)++data LinearEquationTwo = LinearEquationTwo+  { _linearEquationTwoX :: Integer+  , _linearEquationTwoY :: Integer+  , _linearEquationTwoConstant :: Integer+  }++instance Show LinearEquationTwo where+  show (LinearEquationTwo x y c) = "\\x y -> " ++ show x ++ " * x + " ++ show y ++ " * y + " ++ show c++genLinearEquationTwo :: Gen LinearEquationTwo+genLinearEquationTwo = LinearEquationTwo <$> absGenInteger <*> absGenInteger <*> absGenInteger+  where+    absGenInteger = abs <$> genSmallInteger++runLinearEquationTwo :: LinearEquationTwo -> Integer -> Integer -> Integer+runLinearEquationTwo (LinearEquationTwo a b c) x y = a * x + b * y + c++data CubicEquation = CubicEquation+  { _cubicEquationCubic :: Integer+  , _cubicEquationQuadratic :: Integer+  , _cubicEquationLinear :: Integer+  , _cubicEquationConstant :: Integer+  }++instance Show CubicEquation where+  show (CubicEquation x y z c) = "\\x -> " ++ show x ++ " * x ^ 3 + " ++ show y ++ " * x ^ 2 + " ++ show z ++ " * x + " ++ show c++genCubicEquation :: Gen CubicEquation+genCubicEquation = CubicEquation <$> genSmallInteger <*> genSmallInteger <*> genSmallInteger <*> genSmallInteger++runCubicEquation :: CubicEquation -> Integer -> Integer -> Integer -> Integer+runCubicEquation (CubicEquation a b c d) x y z = a * x + b * y + c * z + d
+ src/Hedgehog/Classes/Common/Func.hs view
@@ -0,0 +1,80 @@+module Hedgehog.Classes.Common.Func+  ( func1+  , func2+  , func3+  , func4+  , func5+  , func6++  , Triple(..), reverseTriple, genTriple+  ) where++import Hedgehog+import Data.Functor.Classes (Eq1(..), Show1(..))+import Data.Functor.Compose+import qualified Data.Set as S+import qualified Control.Monad.Trans.Writer.Lazy as WL+import Data.Semigroup++func1 :: Integer -> (Integer, Integer)+func1 i = (div (i + 5) 3, i * i - 2 * i + 1)++func2 :: (Integer, Integer) -> (Bool, Either Ordering Integer)+func2 (a,b) = (odd a, if even a then Left (compare a b) else Right (b + 2))++func3 :: Integer -> Sum Integer+func3 i = Sum (3 * i * i - 7 * i + 4)++func4 :: Integer -> Compose Triple (WL.Writer (S.Set Integer)) Integer+func4 i = Compose $ Triple+  (WL.writer (i * i, S.singleton (i * 7 + 5)))+  (WL.writer (i + 2, S.singleton (i * i + 3)))+  (WL.writer (i * 7, S.singleton 4))++func5 :: Integer -> Triple Integer+func5 i = Triple (i + 2) (i * 3) (i * i)++func6 :: Integer -> Triple Integer+func6 i = Triple (i * i * i) (4 * i - 7) (i * i * i)++reverseTriple :: Triple a -> Triple a+reverseTriple (Triple a b c) = Triple c b a++data Triple a = Triple a a a+  deriving (Show, Eq)++instance Functor Triple where+  fmap f (Triple a b c) = Triple (f a) (f b) (f c)++instance Applicative Triple where+  pure a = Triple a a a+  Triple f g h <*> Triple a b c = Triple (f a) (g b) (h c)++instance Foldable Triple where+  foldMap f (Triple a b c) = f a <> f b <> f c++instance Traversable Triple where+  traverse f (Triple a b c) = Triple <$> f a <*> f b <*> f c++tripleLiftEq :: (a -> b -> Bool) -> Triple a -> Triple b -> Bool+tripleLiftEq p (Triple a1 b1 c1) (Triple a2 b2 c2) =+  p a1 a2 && p b1 b2 && p c1 c2++tripleLiftShowsPrec :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> Int -> Triple a -> ShowS+tripleLiftShowsPrec elemShowsPrec _ p (Triple a b c) = showParen (p > 10)+  $ showString "Triple "+  . elemShowsPrec 11 a+  . showString " "+  . elemShowsPrec 11 b+  . showString " "+  . elemShowsPrec 11 c++instance Eq1 Triple where+  liftEq = tripleLiftEq++instance Show1 Triple where+  liftShowsPrec = tripleLiftShowsPrec++genTriple :: Gen a -> Gen (Triple a)+genTriple gen = Triple <$> gen <*> gen <*> gen+  
+ src/Hedgehog/Classes/Common/Gen.hs view
@@ -0,0 +1,76 @@+{-# LANGUAGE RankNTypes #-}++module Hedgehog.Classes.Common.Gen+  ( genSmallList+  , genSmallNonEmptyList+  , genShowReadPrecedence+  , genSmallString+  , genSmallInteger+  , genSmallSum+  , genCompose+  , genSetInteger++  -- * Used for 'Hedgehog.Classes.ixLaws' +  , genTuple+  , genTuple3+  , genInRange+  , genValidRange+  ) where++import Data.Ix (Ix(..))+import Hedgehog+import Data.Functor.Compose+import qualified Data.Set as S+import Data.Semigroup+import qualified Hedgehog.Gen as Gen+import qualified Hedgehog.Range as Range++genSmallSum :: Gen (Sum Integer)+genSmallSum = fmap Sum genSmallInteger++genSmallInteger :: Gen Integer+genSmallInteger = Gen.integral (Range.linear 0 20)++genSmallNonEmptyList :: Gen a -> Gen [a]+genSmallNonEmptyList gen = Gen.list (Range.linear 1 7) gen++genSmallList :: Gen a -> Gen [a]+genSmallList gen = Gen.list (Range.linear 0 6) gen++genSmallString :: Gen String+genSmallString = Gen.string (Range.linear 0 6) Gen.ascii++-- Haskell uses the operator precedences 0..9, the special function application+-- precedence 10 and the precedence 11 for function arguments. Both show and+-- read instances have to accept this range. According to the Haskell Language+-- Report, the output of derived show instances in precedence context 11 has to+-- be an atomic expression.+genShowReadPrecedence :: Gen Int+genShowReadPrecedence = Gen.element [0..11]++genCompose :: forall f g a. Gen a -> (forall x. Gen x -> Gen (f x)) -> (forall x. Gen x -> Gen (g x)) -> Gen (Compose f g a)+genCompose gen fgen ggen = Compose <$> fgen (ggen gen) ++genTuple :: Gen a -> Gen b -> Gen (a,b)+genTuple a b = (,) <$> a <*> b++genTuple3 :: Gen a -> Gen b -> Gen c -> Gen (a, b, c)+genTuple3 gena genb genc = do+  a <- gena+  b <- genb+  c <- genc+  pure (a, b, c)++genValidRange :: Ix a => Gen a -> Gen (a, a)+genValidRange gen = do+  Gen.filter (\(l,u) -> l <= u) (genTuple gen gen)++genInRange :: (Ix a) => Gen a -> Gen (a, a, a)+genInRange gen = do+  Gen.filter (\(l,u,i) -> inRange (l,u) i) (genTuple3 gen gen gen)+ +genSetInteger :: Gen (S.Set Integer)+genSetInteger = do+  xs <- sequence $ fmap (const genSmallInteger) [1..10 :: Integer]+  pure $ foldMap S.singleton xs+
+ src/Hedgehog/Classes/Common/IO.hs view
@@ -0,0 +1,16 @@+module Hedgehog.Classes.Common.IO+  ( genIO+  , showIO+  ) where++import Hedgehog+import System.IO.Unsafe (unsafePerformIO)++genIO :: Gen a -> Gen (IO a)+genIO gen = fmap pure gen++showIO :: Show a => IO a -> String+showIO io = unsafePerformIO $ do+  x <- fmap show io+  let y = "IO " ++ x+  pure y
+ src/Hedgehog/Classes/Common/Laws.hs view
@@ -0,0 +1,270 @@+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE RecordWildCards #-}++module Hedgehog.Classes.Common.Laws+  ( Laws(..)+  , LawContext(..)++  , lawsCheck+  , lawsCheckOne+  , lawsCheckMany++  , contextualise+  , reduced+  , lawWhere+  , congruency++  , congruent+  , newline+  , tab+  , tab2+  ) where++import Control.Monad.IO.Class (MonadIO(liftIO))+import Data.Monoid (All(..), Ap(..))+import Hedgehog (Gen)+import Hedgehog.Classes.Common.Property (Context(..))+import Hedgehog.Internal.Property (Property(..))+import Hedgehog.Internal.Region (Region)+import Hedgehog.Internal.Report (Report, Result(..), Progress(..), renderProgress, reportStatus)+import Hedgehog.Internal.Runner (checkReport)+import System.Exit (exitFailure)+import qualified Hedgehog.Classes.Common.PP as PP+import qualified Hedgehog.Internal.Region as Region+import qualified Hedgehog.Internal.Seed as Seed++congruent :: String+congruent = " ≡ "++congruency :: String -> String -> String+congruency x y = x ++ congruent ++ y++newline, tab, tab2 :: String+newline = "\n"+tab = "    "+tab2 = "  "++-- | For footnotes+dagger :: String+dagger = "†"++lawWhere :: [String] -> String+lawWhere [] = []+lawWhere (l:ls) = l ++ newline ++ tab2 ++ lawWhere ls++-- | A 'Laws' is the name of the typeclass and the set of named properties associated with that typeclass.+data Laws = Laws+  { lawsTypeClass :: String+  , lawsProperties :: [(String, Property)]+  }++-- | The context surrounding the property test of a law. Use 'contextualise' to turn this into a 'Context'.+data LawContext = LawContext+  { lawContextLawName :: String -- ^ law name+  , lawContextLawBody :: String -- ^ law body+  , lawContextTcName  :: String -- ^ typeclass name+  , lawContextTcProp  :: String -- ^ how to show the specific property test+  , lawContextReduced :: String -- ^ reduced equation, eg "LHS = RHS" where neither LHS nor RHS are reducible+  }++reduced :: Show a => a -> a -> String+reduced lhs rhs = show lhs ++ congruent ++ show rhs++-- | Turn a 'LawContext' into a 'Context'.+contextualise :: LawContext -> Context+contextualise LawContext{..} = Context $ unlines +  [ "When testing the " ++ lawContextLawName ++ " law(" ++ dagger ++"), for the " ++ lawContextTcName ++ " typeclass, the following test failed: "+  , newline ++ lawContextTcProp+  , newline ++ "The reduced test is: "+  , tab2 ++ lawContextReduced+  , newline ++ "The law in question: "+  , tab2 ++ "(" ++ dagger ++ ") " ++ lawContextLawName ++ " Law: " ++ lawContextLawBody+  ]++-- | A convenience function for testing the properties of a typeclass.+--   For example, in GHCi:+--+-- >>> genOrdering :: Gen Ordering; genOrdering = frequency [(1,pure EQ),(1,pure LT),(1,pure GT)]+-- >>> lawsCheck (monoidLaws genOrdering)+--   ✓ <interactive> passed 100 tests.+--   ✓ <interactive> passed 100 tests.+--   ✓ <interactive> passed 100 tests.+--   ✓ <interactive> passed 100 tests.+-- True+lawsCheck ::+     Laws -- ^ The 'Laws' you would like to check.+  -> IO Bool -- ^ 'True' if your tests pass, 'False' otherwise.+lawsCheck = fmap getAll . lawsCheckInternal++-- | A convenience function for testing many typeclass instances of+--   a single type.+--+-- >>> lawsCheckOne (word8 constantBounded) [jsonLaws, showReadLaws]+--   ✓ <interactive> passed 100 tests.+--   ✓ <interactive> passed 100 tests.+--   ✓ <interactive> passed 100 tests.+--   ✓ <interactive> passed 100 tests.+--   ✓ <interactive> passed 100 tests.+--   ✓ <interactive> passed 100 tests.+--   ✓ <interactive> passed 100 tests.+-- True+lawsCheckOne ::+     Gen a -- ^ The generator for your type.+  -> [Gen a -> Laws] -- ^ Functions that take a generator and output 'Laws'.+  -> IO Bool -- ^ 'True' if your tests pass. 'False' otherwise.+lawsCheckOne g = fmap getAll . lawsCheckOneInternal g++-- | A convenience function for checking many typeclass instances of+--   multiple types.+--+-- @+-- import Control.Applicative (liftA2)+--+-- import Data.Map (Map)+-- import Data.Set (Set)+--+-- import qualified Data.List as List+-- import qualified Data.Set as Set+-- import qualified Data.Map as Map+--+-- import qualified Hedgehog.Gen as Gen+-- import qualified Hedgehog.Range as Range+--+-- import Hedgehog (Gen)+-- import Hedgehog.Classes+--+-- -- Generate a small @Set Int@+-- genSet :: Gen (Set Int)+-- genSet = Set.fromList <$> (Gen.list (Range.linear 2 10) (Gen.int Range.constantBounded))+--+-- -- Generate a small @Map String Int@+-- genMap :: Gen (Map String Int)+-- genMap = Map.fromList <$> (liftA2 List.zip genStrings genInts)+--   where+--     rng = Range.linear 2 6+--     genStrings = Gen.list rng (Gen.string rng Gen.lower)+--     genInts = Gen.list rng (Gen.int Range.constantBounded)+--+-- commonLaws :: (Eq a, Monoid a, Show a) => Gen a -> [Laws]+-- commonLaws p = [eqLaws p, monoidLaws p]+--+-- tests :: [(String, [Laws])]+-- tests =+--   [ ("Set Int", commonLaws genSet)+--   , ("Map String Int", commonLaws genMap)+--   ]+-- @+--+-- Now, in GHCi:+--+-- >>> lawsCheckMany tests+--+-- Testing properties for common typeclasses...+--+-- -------------+-- -- Set Int --+-- -------------+-- +--   ✓ <interactive> passed 100 tests.+--   ✓ <interactive> passed 100 tests.+--   ✓ <interactive> passed 100 tests.+--   ✓ <interactive> passed 100 tests.+--   ✓ <interactive> passed 100 tests.+--   ✓ <interactive> passed 100 tests.+--   ✓ <interactive> passed 100 tests.+-- +-- --------------------+-- -- Map String Int --+-- --------------------+-- +--   ✓ <interactive> passed 100 tests.+--   ✓ <interactive> passed 100 tests.+--   ✓ <interactive> passed 100 tests.+--   ✓ <interactive> passed 100 tests.+--   ✓ <interactive> passed 100 tests.+--   ✓ <interactive> passed 100 tests.+--   ✓ <interactive> passed 100 tests.+-- +-- +-- All tests succeeded+-- True+lawsCheckMany ::+     [(String, [Laws])] -- ^ Pairs of type names and their associated laws to test.+  -> IO Bool -- ^ 'True' if your tests pass. 'False' otherwise.+lawsCheckMany = fmap getAll . lawsCheckManyInternal++lawsCheckInternal :: Laws -> IO All+lawsCheckInternal (Laws className properties) =+  flip foldMapA properties $ \(name,p) -> do+    putStr (className ++ ": " ++ name ++ " ")+    All <$> check p++lawsCheckOneInternal :: Gen a -> [Gen a -> Laws] -> IO All+lawsCheckOneInternal p ls = foldMap (lawsCheckInternal . ($ p)) ls++lawsCheckManyInternal :: [(String, [Laws])] -> IO All+lawsCheckManyInternal xs = do+  putStrLn ""+  putStrLn "Testing properties for common typeclasses..."+  putStrLn ""+  r <- flip foldMapA xs $ \(typeName, laws) -> do+    putStrLn $ prettyHeader typeName+    r <- flip foldMapA laws $ \(Laws typeclassName properties) -> do+      flip foldMapA properties $ \(name,p) -> do+        putStr (typeclassName ++ ": " ++ name ++ " ")+        check p >>= \case { True -> pure Good; _ -> pure Bad }+    putStrLn ""+    pure r+  putStrLn ""+  case r of+    Good -> putStrLn "All tests succeeded" *> pure mempty+    Bad  -> do+      putStrLn "One or more tests failed"+      exitFailure++foldMapA :: (Foldable t, Monoid m, Applicative f) => (a -> f m) -> t a -> f m+foldMapA f = getAp . foldMap (Ap . f)++prettyHeader :: String -> String+prettyHeader s = unlines [topLine, middleLine, bottomLine]+  where+    line = replicate (length s + 6) '-'+    topLine = line+    bottomLine = line+    middleLine = "-- " ++ s ++ " --"++data Status = Bad | Good++instance Semigroup Status where+  Good <> x = x+  Bad <> _ = Bad++instance Monoid Status where+  mempty = Good++checkRegion :: MonadIO m+  => Region+  -> Property+  -> m (Report Result)+checkRegion region prop = liftIO $ do+  seed <- liftIO Seed.random +  result <- checkReport (propertyConfig prop) 0 seed (propertyTest prop) $ \progress -> do+    ppprogress <- renderProgress Nothing Nothing progress+    case reportStatus progress of+      Running -> Region.setRegion region ppprogress+      Shrinking _ -> Region.openRegion region ppprogress+  ppresult <- PP.renderResult result+  case reportStatus result of+    Failed _ -> Region.openRegion region ppresult+    GaveUp -> Region.openRegion region ppresult+    OK -> Region.setRegion region ppresult++  pure result ++check :: MonadIO m+  => Property+  -> m Bool+check prop = liftIO . Region.displayRegion $ \region ->+  (== OK) . reportStatus <$> checkRegion region prop+
+ src/Hedgehog/Classes/Common/PP.hs view
@@ -0,0 +1,134 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE ImplicitParams #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}++#if HAVE_QUANTIFIED_CONSTRAINTS+{-# LANGUAGE QuantifiedConstraints #-}+#endif++-- | Reverse-engineered hedgehog internals that don't print out source locations.+module Hedgehog.Classes.Common.PP+  ( ppDiscardCount+  , ppDoc+  , ppName+  , ppResult+  , ppShrinkCount+  , ppShrinkDiscard+  , ppTestCount+  , renderResult+  ) where++import Hedgehog.Range (Size)+import Control.Monad.IO.Class (MonadIO(..))+import qualified Data.List as List+import Hedgehog.Internal.Report+  ( DiscardCount(..), TestCount(..), ShrinkCount(..), Markup(..), Report(..)+  , Result(..), FailureReport(..), renderDoc+  )+import qualified Text.PrettyPrint.Annotated.WL as WL+import Text.PrettyPrint.Annotated.WL ( (<+>) )+import qualified Hedgehog.Internal.Seed as Seed+import Text.PrettyPrint.Annotated.WL (Doc)++ppDoc :: Show x => x -> Doc a+ppDoc = WL.text . show++ppName :: Doc a+ppName = "<interactive>"++ppDiscardCount :: DiscardCount -> Doc a+ppDiscardCount = \case+  DiscardCount 1 -> "1 discard"+  DiscardCount n -> ppDoc n <+> "discards"++ppTestCount :: TestCount -> Doc a+ppTestCount = \case+  TestCount 1 -> "1 test"+  TestCount n -> ppDoc n <+> "tests"++ppShrinkCount :: ShrinkCount -> Doc a+ppShrinkCount = \case+  ShrinkCount 1 -> "1 shrink"+  ShrinkCount n -> ppDoc n <+> "shrinks"++ppShrinkDiscard :: ShrinkCount -> DiscardCount -> Doc Markup+ppShrinkDiscard s d = case (s, d) of+  (0, 0) -> ""+  (0, _) -> " and" <+> ppDiscardCount d+  (_, 0) -> " and" <+> ppShrinkCount s+  (_, _) -> "," <+> ppShrinkCount s <+> "and" <+> ppDiscardCount d++ppResult :: MonadIO m => Report Result -> m (Doc Markup)+ppResult (Report tests discards result) = case result of+  Failed failure -> do+    pfailure <- ppFailure failure+    pure . WL.vsep $+      [ icon FailedIcon '✗' . markup FailedHeader $+          ppName <+>+          "failed after" <+>+          ppTestCount tests <>+          ppShrinkDiscard (failureShrinks failure) discards <>+          "."+      , mempty+      , pfailure+      , mempty+      ] +  +  GaveUp -> pure . icon GaveUpIcon '⚐' . WL.annotate GaveUpHeader $+    ppName <+>+    "gave up after" <+>+    ppDiscardCount discards <>+    ", passed" <+>+    ppTestCount tests <>+    "." +  OK -> pure . icon SuccessIcon '✓' . WL.annotate SuccessHeader $+    ppName <+>+    "passed" <+>+    ppTestCount tests <>+    "."++icon :: Markup -> Char -> Doc Markup -> Doc Markup+icon m i x = WL.annotate m (WL.char i) <+> x++ppTextLines :: String -> [Doc Markup]+ppTextLines = fmap WL.text . List.lines++markup :: Markup -> Doc Markup -> Doc Markup+markup = WL.annotate++gutter :: Markup -> Doc Markup -> Doc Markup+gutter m x = markup m ">" <+> x++ppFailure :: MonadIO m => FailureReport -> m (Doc Markup)+ppFailure (FailureReport size seed _ _inputs0 mlocation0 msg _mdiff msgs0) = do+  msgs <- case mlocation0 of+    Nothing ->+      let msgs1 = msgs0 ++ (if null msg then [] else [msg])+          docs = concatMap ppTextLines msgs1+      in pure docs+    Just _location0 -> +      let l = concatMap ppTextLines msgs0+      in pure l++  let with xs f = if null xs then [] else [f xs]++  pure . WL.indent 2 . WL.vsep . WL.punctuate WL.line $ concat+    [ with msgs WL.vsep+    , [ppReproduce size seed]+    ]++ppReproduce :: Size -> Seed.Seed -> Doc Markup+ppReproduce size seed = WL.vsep+  [ markup ReproduceHeader "This failure can be reproduced by running:"+  , gutter ReproduceGutter . markup ReproduceSource $+      "recheck" <+>+      WL.text (showsPrec 11 size "") <+>+      WL.text (showsPrec 11 seed "") <+>+      "<property>"+  ]++renderResult :: MonadIO m => Report Result -> m String+renderResult x = renderDoc Nothing =<< ppResult x
+ src/Hedgehog/Classes/Common/Property.hs view
@@ -0,0 +1,307 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE ImplicitParams #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}++#if HAVE_QUANTIFIED_CONSTRAINTS+{-# LANGUAGE QuantifiedConstraints #-}+#endif++-- | This module exports hedgehog comparison tests+--   that don't contain CallStack information, since this would+--   expose library internals in error messages.+module Hedgehog.Classes.Common.Property+  ( hLessThan, hGreaterThan+  , heq, heq1, heq2+  , heqCtx, heqCtx1, heqCtx2+  , hneq, hneq1, hneq2+  , hneqCtx, hneqCtx1, hneqCtx2 +  , bar+  , Context(..)+  ) where++import Control.Exception (SomeException(..), displayException)+import Data.Typeable (typeOf)+import GHC.Stack+import Hedgehog.Classes.Common.Compat+import Hedgehog.Internal.Exception (tryEvaluate)+import Hedgehog.Internal.Property (MonadTest, liftTest, mkTest, success, Failure(..), Log(..))+import Text.Show.Pretty (ppShow)+import qualified Data.Char as Char+import qualified Data.List as List++#if HAVE_QUANTIFIED_CONSTRAINTS == 0+import qualified Data.Functor.Classes as C+#endif++bar :: String+bar = "━━━"++bar5 :: String+bar5 = "━━━━━━━━━━━━━━━"++evalNoSrc :: (MonadTest m, HasCallStack) => a -> m a+evalNoSrc x = either (withFrozenCallStack failExceptionNoSrc) pure (tryEvaluate x)++failWithNoSrc :: (MonadTest m, HasCallStack) => String -> m a+failWithNoSrc msg = do+  liftTest $ mkTest (Left $ Failure Nothing "" Nothing, [Footnote msg])+ +failExceptionNoSrc :: (MonadTest m, HasCallStack) => SomeException -> m a+failExceptionNoSrc (SomeException x) = withFrozenCallStack $+  failWithNoSrc $ unlines+    [ bar ++ " Exception: " ++ show (typeOf x) ++ " " ++ bar+      , List.dropWhileEnd Char.isSpace (displayException x)+    ]++-- | You can provide a 'Context' to 'heqCtx','heqCtx1','heqCtx2','hneqCtx','hneqCtx1',or 'hneqCtx2'. The 'Context' is used to provide useful error messages in the event of a failure.+data Context = NoContext | Context String++contextToString :: Context -> String+contextToString = \case+  NoContext -> "No Context provided."+  Context ctx -> bar ++ " Context " ++ bar ++ "\n" ++ ctx ++ bar5++failContext::+  ( MonadTest m, HasCallStack+  , Show a, Show b+  ) => a -> b -> Context -> m ()+failContext _x _y ctx = withFrozenCallStack $+  failWithNoSrc $ contextToString ctx++-- | Fails the test if the right argument is less than or equal to the left.+-- see https://github.com/hedgehogqa/haskell-hedgehog/pull/196 +hLessThan :: (MonadTest m, Ord a, Show a, HasCallStack) => a -> a -> m ()+hLessThan x y = do+  ok <- withFrozenCallStack $ evalNoSrc (x < y)+  if ok+    then success+    else withFrozenCallStack $ failWithNoSrc $ unlines+      [ bar ++ "Not Less Than " ++ bar+      , ppShow x ++ " is not less than " ++ ppShow y+      ]++-- | Fails the test if the right argument is greater than or equal to the left.+-- see https://github.com/hedgehogqa/haskell-hedgehog/pull/196+hGreaterThan :: (MonadTest m, Ord a, Show a, HasCallStack) => a -> a -> m ()+hGreaterThan x y = do+  ok <- withFrozenCallStack $ evalNoSrc (x > y)+  if ok+    then success+    else withFrozenCallStack $ failWithNoSrc $ unlines+      [ bar ++ "Not Greater Than " ++ bar+      , ppShow x ++ " is not greater than " ++ ppShow y+      ]++infix 4 `hneq`++-- | Passes the test if the given arguments are not equal. Otherwise fails+--   with the given 'Context'.+hneqCtx ::+  ( MonadTest m+  , HasCallStack+  , Eq a+  , Show a+  ) => a -> a -> Context -> m ()+hneqCtx x y ctx = do+  ok <- withFrozenCallStack $ evalNoSrc (x `neq` y)+  if ok+    then success+    else withFrozenCallStack $ failContext x y ctx++-- | Passes the test if the given arguments are not equal. Otherwise fails+--   with 'NoContext'.+hneq ::+  ( MonadTest m+  , HasCallStack+  , Eq a+  , Show a+  ) => a -> a -> m ()+hneq x y = hneqCtx x y NoContext++infix 4 `heq`++-- | Passes the test if the given arguments are equal. Otherwise fails+--   with the given 'Context'.+heqCtx ::+    ( MonadTest m+    , HasCallStack+    , Eq a+    , Show a+    ) => a -> a -> Context -> m ()+heqCtx x y ctx = do+  ok <- withFrozenCallStack $ evalNoSrc (x `eq` y)+  if ok+    then success+    else withFrozenCallStack $ failContext x y ctx++-- | Passes the test if the given arguments are equal. Otherwise fails+--   with 'NoContext'.+heq ::+    ( MonadTest m+    , HasCallStack+    , Eq a+    , Show a+    ) => a -> a -> m ()+heq x y = heqCtx x y NoContext++infix 4 `heq1`++-- | Passes the test if the given arguments are not equal. Otherwise fails+--   with the given 'Context'.+hneqCtx1 ::+     ( MonadTest m+     , HasCallStack+     , Eq a+     , Show a+#if HAVE_QUANTIFIED_CONSTRAINTS+     , forall x. Eq x => Eq (f x)+     , forall x. Show x => Show (f x)+#else+     , C.Eq1 f, C.Show1 f+#endif +     ) => f a -> f a -> Context -> m ()+hneqCtx1 x y ctx = do+  ok <- withFrozenCallStack $ evalNoSrc (x `neq1` y)+  if ok+    then success+    else withFrozenCallStack $ failContext x y ctx++-- | Passes the test if the given arguments are not equal. Otherwise fails+--   with 'NoContext'.+hneq1 ::+     ( MonadTest m+     , HasCallStack+     , Eq a+     , Show a+#if HAVE_QUANTIFIED_CONSTRAINTS+     , forall x. Eq x => Eq (f x)+     , forall x. Show x => Show (f x)+#else+     , C.Eq1 f, C.Show1 f+#endif +     ) => f a -> f a -> m ()+hneq1 x y = hneqCtx1 x y NoContext++-- | Passes the test if the given arguments are equal. Otherwise fails+--   with the given 'Context'.+heqCtx1 ::+     ( MonadTest m+     , HasCallStack+     , Eq a+     , Show a+#if HAVE_QUANTIFIED_CONSTRAINTS+     , forall x. Eq x => Eq (f x)+     , forall x. Show x => Show (f x)+#else+     , C.Eq1 f, C.Show1 f+#endif +     ) => f a -> f a -> Context -> m ()+heqCtx1 x y ctx = do+  ok <- withFrozenCallStack $ evalNoSrc (x `eq1` y)+  if ok+    then success+    else withFrozenCallStack $ failContext x y ctx++-- | Passes the test if the given arguments are equal. Otherwise fails+--   with 'NoContext'.+heq1 ::+     ( MonadTest m+     , HasCallStack+     , Eq a+     , Show a+#if HAVE_QUANTIFIED_CONSTRAINTS+     , forall x. Eq x => Eq (f x)+     , forall x. Show x => Show (f x)+#else+     , C.Eq1 f, C.Show1 f+#endif +     ) => f a -> f a -> m ()+heq1 x y = heqCtx1 x y NoContext++infix 4 `heq2`++-- | Passes the test if the given arguments are equal. Otherwise fails+--   with the given 'Context'.+heqCtx2 ::+     ( MonadTest m+     , HasCallStack+     , Eq a+     , Eq b+     , Show a+     , Show b+#if HAVE_QUANTIFIED_CONSTRAINTS+     , forall x y. (Eq x, Eq y) => Eq (f x y)+     , forall x y. (Show x, Show y) => Show (f x y)+#else+     , C.Eq2 f, C.Show2 f+#endif +     ) => f a b -> f a b -> Context -> m ()+heqCtx2 x y ctx = do+  ok <- withFrozenCallStack $ evalNoSrc (x `eq2` y)+  if ok+    then success+    else withFrozenCallStack $ failContext x y ctx++-- | Passes the test if the given arguments are equal. Otherwise fails+--   with 'NoContext'.+heq2 ::+     ( MonadTest m+     , HasCallStack+     , Eq a+     , Eq b+     , Show a+     , Show b+#if HAVE_QUANTIFIED_CONSTRAINTS+     , forall x y. (Eq x, Eq y) => Eq (f x y)+     , forall x y. (Show x, Show y) => Show (f x y)+#else+     , C.Eq2 f, C.Show2 f+#endif +     ) => f a b -> f a b -> m ()+heq2 x y = heqCtx2 x y NoContext++infix 4 `hneq2`++-- | Passes the test if the given arguments are not equal. Otherwise fails+--   with the given 'Context'.+hneqCtx2 ::+     ( MonadTest m+     , HasCallStack+     , Eq a+     , Eq b+     , Show a+     , Show b+#if HAVE_QUANTIFIED_CONSTRAINTS+     , forall x y. (Eq x, Eq y) => Eq (f x y)+     , forall x y. (Show x, Show y) => Show (f x y)+#else+     , C.Eq2 f, C.Show2 f+#endif +     ) => f a b -> f a b -> Context -> m ()+hneqCtx2 x y ctx = do+  ok <- withFrozenCallStack $ evalNoSrc (x `neq2` y)+  if ok+    then success+    else withFrozenCallStack $ failContext x y ctx++-- | Passes the test if the given arguments are not equal. Otherwise fails+--   with 'NoContext'.+hneq2 ::+     ( MonadTest m+     , HasCallStack+     , Eq a+     , Eq b+     , Show a+     , Show b+#if HAVE_QUANTIFIED_CONSTRAINTS+     , forall x y. (Eq x, Eq y) => Eq (f x y)+     , forall x y. (Show x, Show y) => Show (f x y)+#else+     , C.Eq2 f, C.Show2 f+#endif +     ) => f a b -> f a b -> m ()+hneq2 x y = hneqCtx2 x y NoContext+
+ src/Hedgehog/Classes/Contravariant.hs view
@@ -0,0 +1,70 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE QuantifiedConstraints #-}+{-# LANGUAGE RankNTypes #-}++module Hedgehog.Classes.Contravariant (contravariantLaws) where++import Data.Functor.Contravariant (Contravariant(..))++import Hedgehog+import Hedgehog.Classes.Common++-- | Tests the following 'Contravariant' laws:+--+-- [__Identity__]: @'contramap' 'id'@ ≡ @'id'@+-- [__Composition__]: @'contramap' f '.' 'contramap' g@ ≡ @'contramap' (g '.' f)@+contravariantLaws ::+  ( Contravariant f+  , forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)+  ) => (forall x. Gen x -> Gen (f x)) -> Laws+contravariantLaws gen = Laws "Contravariant"+  [ ("Identity", contravariantIdentity gen)+  , ("Composition", contravariantComposition gen)+  ]++contravariantIdentity ::+  ( Contravariant f+  , forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)+  ) => (forall x. Gen x -> Gen (f x)) -> Property+contravariantIdentity fgen = property $ do+  a <- forAll $ fgen genSmallInteger+  let lhs = contramap id a+  let rhs = id a+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Identity", lawContextLawBody = "contramap id" `congruency` "id"+        , lawContextTcName = "Contravariant", lawContextTcProp =+            let showA = show a+            in lawWhere+              [ "contramap id x" `congruency` "id x, where"+              , "x = " ++ showA+              ]+        , lawContextReduced = reduced lhs rhs+        }+  heqCtx1 lhs rhs ctx++contravariantComposition ::+  ( Contravariant f+  , forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)+  ) => (forall x. Gen x -> Gen (f x)) -> Property+contravariantComposition fgen = property $ do+  a <- forAll $ fgen genSmallInteger+  f' <- forAll genQuadraticEquation+  g' <- forAll genQuadraticEquation+  let f = runQuadraticEquation f'+  let g = runQuadraticEquation g'+  let lhs = contramap f (contramap g a)+  let rhs = contramap (g . f) a+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Composition", lawContextLawBody = "contramap f . contramap g" `congruency` "contramap (g . f)"+        , lawContextTcName = "Contravariant", lawContextTcProp =+            let showF = show f'; showG = show g'; showA = show a;+            in lawWhere+                 [ "contramap f . contramap g $ a" `congruency` "contramap (g . f) a, where"+                 , "f = " ++ showF+                 , "g = " ++ showG+                 , "a = " ++ showA+                 ]+        , lawContextReduced = reduced lhs rhs+        }+  heqCtx1 lhs rhs ctx+
+ src/Hedgehog/Classes/Enum.hs view
@@ -0,0 +1,101 @@+{-# LANGUAGE ScopedTypeVariables #-}++module Hedgehog.Classes.Enum (enumLaws, boundedEnumLaws) where++import Hedgehog+import Hedgehog.Classes.Common++import qualified Hedgehog.Gen as Gen++-- | Tests the following 'Enum' laws:+--+-- [__Succ-Pred Identity__]: @'succ' '.' 'pred'@ ≡ @'id'@+-- [__Pred-Succ Identity__]: @'pred' '.' 'succ'@ ≡ @'id'@+enumLaws :: (Enum a, Eq a, Show a) => Gen a -> Laws+enumLaws gen = Laws "Enum"+  [ ("Succ Pred Identity", succPredIdentity gen)+  , ("Pred Succ Identity", predSuccIdentity gen)+  ]++-- | Tests the same laws as 'enumLaws', but uses the 'Bounded'+--   constraint to ensure that 'succ' and 'pred' behave as though+--   they are total. This should always be preferred if your type+--   has a 'Bounded' instance.+boundedEnumLaws :: (Bounded a, Enum a, Eq a, Show a) => Gen a -> Laws+boundedEnumLaws gen = Laws "Bounded Enum"+  [ ("Succ Pred Identity", succPredBoundedIdentity gen)+  , ("Pred Succ Identity", predSuccBoundedIdentity gen)+  ]++succPredIdentity :: forall a. (Enum a, Eq a, Show a) => Gen a -> Property+succPredIdentity gen = property $ do+  x <- forAll gen+  let lhs = succ (pred x); rhs = x;+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Succ-Pred Identity"+        , lawContextLawBody = "succ . pred" `congruency` "id"+        , lawContextTcName = "Enum"+        , lawContextTcProp =+            let showX = show x+            in lawWhere+              [ "succ . pred $ x" `congruency` "id x, where"+              , "x = " ++ showX+              ]+        , lawContextReduced = reduced lhs rhs+        }+  heqCtx lhs rhs ctx++predSuccIdentity :: forall a. (Enum a, Eq a, Show a) => Gen a -> Property+predSuccIdentity gen = property $ do+  x <- forAll gen+  let lhs = pred (succ x); rhs = x;+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Pred-Succ Identity"+        , lawContextLawBody = "pred . succ" `congruency` "id"+        , lawContextTcName = "Enum"+        , lawContextTcProp =+            let showX = show x+            in lawWhere+              [ "pred . succ $ x" `congruency` "id x, where"+              , "x = " ++ showX+              ]+        , lawContextReduced = reduced lhs rhs+        }+  heqCtx lhs rhs ctx++succPredBoundedIdentity :: forall a. (Bounded a, Enum a, Eq a, Show a) => Gen a -> Property+succPredBoundedIdentity gen = property $ do+  x <- forAll $ Gen.filter (/= minBound) gen+  let lhs = succ (pred x); rhs = x;+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Succ-Pred Identity"+        , lawContextLawBody = "succ . pred" `congruency` "id"+        , lawContextTcName = "Enum"+        , lawContextTcProp =+            let showX = show x+            in lawWhere+              [ "succ . pred $ x" `congruency` "id x, where"+              , "x = " ++ showX+              ]+        , lawContextReduced = reduced lhs rhs+        }+  heqCtx lhs rhs ctx++predSuccBoundedIdentity :: forall a. (Bounded a, Enum a, Eq a, Show a) => Gen a -> Property+predSuccBoundedIdentity gen = property $ do+  x <- forAll $ Gen.filter (/= maxBound) gen+  let lhs = pred (succ x); rhs = x;+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Pred-Succ Identity"+        , lawContextLawBody = "pred . succ" `congruency` "id"+        , lawContextTcName = "Enum"+        , lawContextTcProp =+            let showX = show x+            in lawWhere+              [ "pred . succ $ x" `congruency` "id x, where"+              , "x = " ++ showX+              ]+        , lawContextReduced = reduced lhs rhs+        }+  heqCtx lhs rhs ctx+  
+ src/Hedgehog/Classes/Eq.hs view
@@ -0,0 +1,94 @@+{-# LANGUAGE ScopedTypeVariables #-}++module Hedgehog.Classes.Eq (eqLaws) where++import Hedgehog+import Hedgehog.Classes.Common++-- | Tests the following 'Eq' laws:+--+-- [__Reflexivity__]: @x '==' x@ ≡ @'True'@+-- [__Symmetry__]: @x '==' y@ ≡ @y '==' x@+-- [__Transitivity__]: @x '==' y '&&' y '==' z@ ≡ @x '==' z@+-- [__Substitutivity__]: @x '==' y@ ≡ @f x '==' f y@+-- [__Negation__]: @x '/=' y@ ≡ @'not' (x '==' y)@+eqLaws :: (Eq a, Show a) => Gen a -> Laws+eqLaws gen = Laws "Eq"+  [ ("Transitive", eqTransitive gen)+  , ("Symmetric", eqSymmetric gen)  +  , ("Reflexive", eqReflexive gen) +  , ("Negation", eqNegation gen) +  ]++eqTransitive :: forall a. (Eq a, Show a) => Gen a -> Property+eqTransitive gen = property $ do+  a <- forAll gen+  b <- forAll gen+  c <- forAll gen+  let lhs = a == b && b == c; rhs = a == c+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Transitivity", lawContextLawBody = "a == b ∧ b == c" `congruency` "a == c"+        , lawContextTcName = "Eq", lawContextTcProp =+            let showA = show a; showB = show b; showC = show c;+            in lawWhere+              [ "a == b ∧ b == c" `congruency` "a == c, where"+              , "a = " ++ showA+              , "b = " ++ showB+              , "c = " ++ showC+              ]+        , lawContextReduced = reduced lhs rhs+        }+  case a == b of+    True -> case b == c of { True -> heqCtx a c ctx; False -> hneqCtx a c ctx }+    False -> case b == c of { True -> hneqCtx a c ctx; False -> success }++eqSymmetric :: forall a. (Eq a, Show a) => Gen a -> Property+eqSymmetric gen = property $ do+  a <- forAll gen+  b <- forAll gen+  let lhs = a == b; rhs = b == a+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Symmetry", lawContextLawBody = "a == b" `congruency` "b == a"+        , lawContextTcName = "Eq", lawContextTcProp =+            let showA = show a; showB = show b;+            in lawWhere+              [ "a == b" `congruency` "b == a, where"+              , "a = " ++ showA+              , "b = " ++ showB+              ]+        , lawContextReduced = reduced lhs rhs+        }+  heqCtx lhs rhs ctx++eqReflexive :: forall a. (Eq a, Show a) => Gen a -> Property+eqReflexive gen = property $ do+  a <- forAll gen+  let lhs = a+  let rhs = a+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Reflexivity", lawContextLawBody = "a" `congruency` "a"+        , lawContextTcName = "Eq"+        , lawContextTcProp = let showA = show a in lawWhere [ "a" `congruency` "a, where", "a = " ++ showA ]+        , lawContextReduced = reduced a a+        }+  heqCtx lhs rhs ctx++eqNegation :: forall a. (Eq a, Show a) => Gen a -> Property+eqNegation gen = property $ do+  x <- forAll gen+  y <- forAll gen+  let lhs = x /= y+  let rhs = not (x == y)+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Negation", lawContextLawBody = "x /= y" `congruency` "not (x == y)"+        , lawContextTcName = "Eq"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showX = show x; showY = show y;+            in lawWhere+              [ "x /= y" `congruency` "not (x == y), where"+              , "x = " ++ showX+              , "y = " ++ showY+              ]+        }+  heqCtx lhs rhs ctx
+ src/Hedgehog/Classes/Foldable.hs view
@@ -0,0 +1,384 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE QuantifiedConstraints #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE LambdaCase #-}++module Hedgehog.Classes.Foldable (foldableLaws) where++import Hedgehog+import Hedgehog.Classes.Common++import Control.Monad.IO.Class (MonadIO(..))+import Control.Exception (ErrorCall(..), try, evaluate)+import Data.Monoid (Sum(..), Endo(..), Dual(..))+import qualified Data.Foldable as Foldable++-- | Tests the following 'Foldable' laws:+--+-- [__Fold__]: @'Foldable.fold' ≡ 'Foldable.foldMap' 'id'@+-- [__FoldMap__]: @'Foldable.foldMap' f ≡ 'Foldable.foldr' ('mappend' '.' f) 'mempty'@+-- [__Foldr__]: @'Foldable.foldr' f z t ≡ 'appEndo' ('Foldable.foldMap' ('Endo' '.' f) t) z@+-- [__Foldr'__]: @'Foldable.foldr'' f z0 t ≡ 'Foldable.foldl' f' 'id' t z0, where f' k x z = k '$!' f x z@+-- [__Foldl__]: @'Foldable.foldl' f z t ≡ 'appEndo' ('getDual' ('Foldable.foldMap' ('Dual' '.' 'Endo' '.' 'flip' f) t)) z@+-- [__Foldl'__]: @'Foldable.foldl'' f z0 xs ≡ 'Foldable.foldr' f' 'id' xs z0, where f' x k z = k '$!' f z x@+-- [__Foldl1__]: @'Foldable.foldl1' f t ≡ let (x:xs) = 'Foldable.toList' t in 'foldl' f x xs@+-- [__Foldr1__]: @'Foldable.foldr1' f t ≡ let (xs,x)@ = @unsnoc ('Foldable.toList' t) in 'foldr' f x xs@+-- [__ToList__]: @'Foldable.toList' ≡ 'Foldable.foldr' (:) []@+-- [__Null__]: @'Foldable.null' ≡ 'Foldable.foldr' ('const' ('const' 'False')) 'True'@+-- [__Length__]: @'Foldable.length' ≡ 'getSum' '.' 'Foldable.foldMap' ('const' ('Sum' 1))@+foldableLaws ::+  ( Foldable f+  , forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)+  ) => (forall x. Gen x -> Gen (f x)) -> Laws+foldableLaws gen = Laws "Foldable"+  [ ("fold", foldableFold gen)+  , ("foldMap", foldableFoldMap gen)+  , ("foldr", foldableFoldr gen)+  , ("foldr'", foldableFoldr' gen)+  , ("foldl", foldableFoldl gen)+  , ("foldl'", foldableFoldl' gen)+  , ("foldl1", foldableFoldl1 gen)+  , ("foldr1", foldableFoldr1 gen)+  , ("toList", foldableToList gen)+  , ("null", foldableNull gen)+  , ("length", foldableLength gen)+  ]++foldableFold ::+  ( Foldable f+  , forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)+  ) => (forall x. Gen x -> Gen (f x)) -> Property+foldableFold fgen = property $ do+  a <- forAll $ fgen genSmallSum+  let lhs = Foldable.fold a+  let rhs = Foldable.foldMap id a+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Fold"+        , lawContextLawBody = "fold" `congruency` "foldMap id"+        , lawContextTcName = "Foldable"+        , lawContextTcProp =+            let showA = show a+            in lawWhere+              [ "fold a" `congruency` "foldMap id a, where"+              , "a = " ++ showA+              ]+        , lawContextReduced = reduced lhs rhs +        } ++  heqCtx lhs rhs ctx++foldableFoldMap ::+  ( Foldable f+  , forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)+  ) => (forall x. Gen x -> Gen (f x)) -> Property+foldableFoldMap fgen = property $ do+  a <- forAll $ fgen genSmallInteger+  e <- forAll genQuadraticEquation+  let f = Sum . runQuadraticEquation e+  let lhs = Foldable.foldMap f a+  let rhs = Foldable.foldr (mappend . f) mempty a+  let ctx = contextualise $ LawContext+        { lawContextLawName = "FoldMap"+        , lawContextLawBody = "foldMap f" `congruency` "foldr (mappend . f) mempty"+        , lawContextTcName = "Foldable"+        , lawContextTcProp =+            let showA = show a+                showF = "Sum $ " ++ show e+            in lawWhere+              [ "foldMap f a" `congruency` "foldr (mappend . f) mempty  a, where"+              , "f = " ++ showF+              , "a = " ++ showA+              ]+        , lawContextReduced = reduced lhs rhs +        } +  heqCtx lhs rhs ctx++foldableFoldr ::+  ( Foldable f+  , forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)+  ) => (forall x. Gen x -> Gen (f x)) -> Property+foldableFoldr fgen = property $ do+  e <- forAll genLinearEquationTwo+  z <- forAll genSmallInteger+  t <- forAll $ fgen genSmallInteger+  let f = runLinearEquationTwo e+  let lhs = Foldable.foldr f z t+  let rhs = appEndo (Foldable.foldMap (Endo . f) t) z+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Foldr"+        , lawContextLawBody = "foldr f z t" `congruency` "appEndo (foldMap (Endo . f) t) z"+        , lawContextTcName = "Foldable"+        , lawContextTcProp =+            let showT = show t+                showF = show e+                showZ = show z+            in lawWhere+              [ "foldr f z t" `congruency` "appEndo (foldMap (Endo . f) t) z"+              , "f = " ++ showF+              , "z = " ++ showZ+              , "t = " ++ showT+              ]+        , lawContextReduced = reduced lhs rhs +        } +  heqCtx lhs rhs ctx+ +foldableFoldl ::+  ( Foldable f+  , forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)+  ) => (forall x. Gen x -> Gen (f x)) -> Property+foldableFoldl fgen = property $ do+  e <- forAll genLinearEquationTwo+  z <- forAll genSmallInteger+  t <- forAll $ fgen genSmallInteger+  let f = runLinearEquationTwo e+  let lhs = Foldable.foldl f z t+  let rhs = appEndo (getDual (Foldable.foldMap (Dual . Endo . flip f) t)) z+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Foldl"+        , lawContextLawBody = "foldl f z t" `congruency` "appEndo (getDual (foldMap (Dual . Endo . flip f) t)) z"+        , lawContextTcName = "Foldable"+        , lawContextTcProp =+            let showT = show t+                showF = show e+                showZ = show z+            in lawWhere+              [ "foldl f z t" `congruency` "appEndo (getDual (foldMap (Dual . Endo . flip f) t)) z"+              , "f = " ++ showF+              , "z = " ++ showZ+              , "t = " ++ showT+              ]+        , lawContextReduced = reduced lhs rhs +        } +  heqCtx lhs rhs ctx++ctxNotStrict :: String -> Context+ctxNotStrict str = Context $ "Your implementation of " ++ str ++ " is not strict."++foldableFoldr' ::+  ( Foldable f+  , forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)+  ) => (forall x. Gen x -> Gen (f x)) -> Property+foldableFoldr' fgen = property $ do+  xs <- forAll $ fgen (genBottom genSmallInteger)+  let f :: Bottom Integer -> Integer -> Integer+      f a b = case a of+        BottomUndefined -> error "foldableFoldr': your foldr' is not strict!"+        BottomValue v -> if even v then v else b+  z0 <- forAll genSmallInteger+  (rhs, ctx1) <- liftIO $ do+    let f' k x z = k $! f x z+    e <- try (evaluate (Foldable.foldl f' id xs z0))+    case e of+      Left (_ :: ErrorCall) -> pure (Nothing, ctxNotStrict "foldr'")+      Right i -> pure (Just i, NoContext)+  (lhs, ctx2) <- liftIO $ do+    e <- try (evaluate (Foldable.foldr' f z0 xs))+    case e of+      Left (_ :: ErrorCall) -> pure (Nothing, ctxNotStrict "foldr'")+      Right i -> pure (Just i, NoContext)+  let ctx = case ctx1 of+        NoContext -> case ctx2 of+          NoContext -> contextualise $ LawContext+            { lawContextLawName = "Foldr'"+            , lawContextLawBody = "foldr' f z0 t" `congruency` "foldl f' id t z0, where f' k x z = k $! f x z"+            , lawContextTcName = "Foldable"+            , lawContextTcProp =+                let showT = show xs+                    showF = "\\a b -> case a of\n  BottomUndefined -> error \"foldableFoldr': not strict\"\n  BottomValue v -> if even v then v else b"+                    showZ = show z0+                in lawWhere+                  [ "foldr' f z0 t" `congruency` "foldl f' id t z0, where f' k x z = k $! f x z"+                  , "f = " ++ showF+                  , "z0 = " ++ showZ+                  , "t = " ++ showT+                  ]+            , lawContextReduced = reduced lhs rhs +            } +          c2 -> c2+        c1 -> c1+  heqCtx lhs rhs ctx++foldableFoldl' ::+  ( Foldable f+  , forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)+  ) => (forall x. Gen x -> Gen (f x)) -> Property+foldableFoldl' fgen = property $ do+  xs <- forAll $ fgen (genBottom genSmallInteger)+  let f :: Integer -> Bottom Integer -> Integer+      f a b = case b of+        BottomUndefined -> error "foldableFoldl': your foldl' is not strict!"+        BottomValue v -> if even v then a else v+  let z0 = 0+  (rhs,ctx1) <- liftIO $ do+    let f' x k z = k $! f z x+    e <- try (evaluate (Foldable.foldr f' id xs z0))+    case e of+      Left (_ :: ErrorCall) -> pure (Nothing, ctxNotStrict "foldl'")+      Right i -> pure (Just i, NoContext)+  (lhs,ctx2) <- liftIO $ do+    e <- try (evaluate (Foldable.foldl' f z0 xs))+    case e of+      Left (_ :: ErrorCall) -> pure (Nothing, ctxNotStrict "foldl'")+      Right i -> pure (Just i, NoContext) +  let ctx = case ctx1 of+        NoContext -> case ctx2 of+          NoContext -> contextualise $ LawContext+            { lawContextLawName = "Foldl'"+            , lawContextLawBody = "foldl' f z0 xs" `congruency` "foldr f' id xs z0, where f' x k z = k $! f z x"+            , lawContextTcName = "Foldable"+            , lawContextTcProp =+                let showT = show xs+                    showF = "\\a b -> case a of\n  BottomUndefined -> error \"foldableFoldr': not strict\"\n  BottomValue v -> if even v then v else b"+                    showZ = show z0+                in lawWhere+                  [ "foldl' f z0 xs" `congruency` "foldr f' id xs z0, where f' x k z = k $! f z x"+                  , "f = " ++ showF+                  , "z0 = " ++ showZ+                  , "t = " ++ showT+                  ]+            , lawContextReduced = reduced lhs rhs +            } +          c2 -> c2+        c1 -> c1+  heqCtx lhs rhs ctx+ +foldableFoldl1 ::+  ( Foldable f+  , forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)+  ) => (forall x. Gen x -> Gen (f x)) -> Property+foldableFoldl1 fgen = property $ do+  e <- forAll genLinearEquationTwo+  t <- forAll $ fgen genSmallInteger+  case compatToList t of+    [] -> success+    (x:xs) ->+      let f = runLinearEquationTwo e+          lhs = Foldable.foldl1 f t+          rhs = Foldable.foldl f x xs+          ctx = contextualise $ LawContext+            { lawContextLawName = "Foldl1"+            , lawContextLawBody = "foldl1 f t" `congruency` "let (x:xs) = toList t in foldl f x xs"+            , lawContextTcName = "Foldable"+            , lawContextTcProp =+                let showF = show e+                    showT = show t+                    showX = show x+                    showXS = show xs+                in lawWhere+                  [ "foldl1 f t" `congruency` "let (x:xs) = toList t in foldl f x xs, where"+                  , "f = " ++ showF+                  , "t = " ++ showT+                  , "x = " ++ showX+                  , "xs = " ++ showXS+                  ] +            , lawContextReduced = reduced lhs rhs+            }+      in heqCtx lhs rhs ctx++foldableFoldr1 ::+  ( Foldable f+  , forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)+  ) => (forall x. Gen x -> Gen (f x)) -> Property+foldableFoldr1 fgen = property $ do+  e <- forAll genLinearEquationTwo+  t <- forAll $ fgen genSmallInteger+  case unsnoc (compatToList t) of+    Nothing -> success+    Just (xs, x) ->+      let f = runLinearEquationTwo e+          lhs = Foldable.foldr1 f t+          rhs = Foldable.foldr f x xs+          ctx = contextualise $ LawContext+            { lawContextLawName = "Foldr1"+            , lawContextLawBody = "foldr1 f t" `congruency` "let (xs, x) = unsnoc (toList t) in foldr f x xs"+            , lawContextTcName = "Foldable"+            , lawContextTcProp =+                let showF = show e+                    showT = show t+                    showX = show x+                    showXS = show xs+                in lawWhere+                  [ "foldr1 f t" `congruency` "let (xs, x) = unsnoc (toList t) in foldr f x xs, where"+                  , "f = " ++ showF+                  , "t = " ++ showT+                  , "x = " ++ showX+                  , "xs = " ++ showXS+                  ]+            , lawContextReduced = reduced lhs rhs+            }+      in heqCtx lhs rhs ctx++foldableToList ::+  ( Foldable f+  , forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)+  ) => (forall x. Gen x -> Gen (f x)) -> Property+foldableToList fgen = property $ do+  t <- forAll $ fgen genSmallInteger+  let lhs = Foldable.toList t+  let rhs = Foldable.foldr (:) [] t+  let ctx = contextualise $ LawContext+        { lawContextLawName = "ToList"+        , lawContextLawBody = "toList" `congruency` "foldr (:) []"+        , lawContextTcName = "Foldable"+        , lawContextTcProp =+            let showT = show t+            in lawWhere+              [ "toList t" `congruency` "foldr (:) [] t, where"+              , "t = " ++ showT+              ]+        , lawContextReduced = reduced lhs rhs+        } +  heqCtx lhs rhs ctx++foldableNull ::+  ( Foldable f+  , forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)+  ) => (forall x. Gen x -> Gen (f x)) -> Property+foldableNull fgen = property $ do+  t <- forAll $ fgen genSmallInteger+  let lhs = Foldable.null t+  let rhs = Foldable.foldr (const (const False)) True t+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Null"+        , lawContextLawBody = "null" `congruency` "foldr (const (const False)) True"+        , lawContextTcName = "Foldable"+        , lawContextTcProp =+            let showT = show t+            in lawWhere+              [ "null t" `congruency` "foldr (const (const False)) True t, where"+              , "t = " ++ showT+              ]+        , lawContextReduced = reduced lhs rhs+        } +  heqCtx lhs rhs ctx  ++foldableLength ::+  ( Foldable f+  , forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)+  ) => (forall x. Gen x -> Gen (f x)) -> Property+foldableLength fgen = property $ do+  t <- forAll $ fgen genSmallInteger+  let lhs = Foldable.length t+  let rhs = getSum (Foldable.foldMap (const (Sum 1)) t)+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Length"+        , lawContextLawBody = "length" `congruency` "getSum . foldMap (const (Sum 1))"+        , lawContextTcName = "Foldable"+        , lawContextTcProp =+            let showT = show t+            in lawWhere+              [ "length t" `congruency` "getSum . foldMap (const (Sum 1)) $ t, where"+              , "t = " ++ showT+              ]+        , lawContextReduced = reduced lhs rhs+        }+  heqCtx lhs rhs ctx++unsnoc :: [a] -> Maybe ([a], a)+unsnoc = \case+  [] -> Nothing+  [x] -> Just ([], x)+  (x:y:xs) -> fmap (\(bs,b) -> (x:bs,b)) (unsnoc (y : xs))++compatToList :: Foldable f => f a -> [a]+compatToList = Foldable.foldMap (\x -> [x])
+ src/Hedgehog/Classes/Functor.hs view
@@ -0,0 +1,94 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE QuantifiedConstraints #-}+{-# LANGUAGE RankNTypes #-}++module Hedgehog.Classes.Functor (functorLaws) where++import Hedgehog+import Hedgehog.Classes.Common++-- | Tests the following 'Functor' laws:+--+-- [__Identity__]: @'fmap' 'id'@ ≡ @'id'@+-- [__Composition__]: @'fmap' f '.' 'fmap' g@ ≡ @'fmap' (f '.' g)@+-- [__Const__]: @'fmap' ('const' x)@ ≡ @x '<$'@+functorLaws ::+  ( Functor f+  , forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)+  ) => (forall x. Gen x -> Gen (f x)) -> Laws+functorLaws gen = Laws "Functor"+  [ ("Identity", functorIdentity gen)+  , ("Composition", functorComposition gen)+  , ("Const", functorConst gen)+  ]++functorIdentity ::+  ( Functor f+  , forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)+  ) => (forall x. Gen x -> Gen (f x)) -> Property+functorIdentity fgen = property $ do+  a <- forAll $ fgen genSmallInteger+  let lhs = fmap id a+  let rhs = id a+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Identity", lawContextTcName = "Functor"+        , lawContextLawBody = "fmap id" `congruency` "id"+        , lawContextTcProp =+            let showA = show a+            in lawWhere+              [ "fmap id a" `congruency` "id a, where"+              , "a = " ++ showA+              ]+        , lawContextReduced = reduced lhs rhs+        } +  heqCtx lhs rhs ctx++functorComposition ::+  ( Functor f+  , forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)+  ) => (forall x. Gen x -> Gen (f x)) -> Property+functorComposition fgen = property $ do+  a <- forAll $ fgen genSmallInteger+  let f = func2; g = func1 +  let lhs = fmap f (fmap g a)+  let rhs = fmap (f . g) a+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Composition", lawContextTcName = "Functor"+        , lawContextLawBody = "fmap f . fmap g" `congruency` "fmap (f . g)"+        , lawContextTcProp =+            let showA = show a+                showF = "\\(a,b) -> (odd a, if even a then Left (compare a b) else Right (b + 2)"+                showG = "\\i -> (div (i + 5) 3, i * i - 2 * i + 1)"+            in lawWhere+              [ "fmap f . fmap g $ a" `congruency` "fmap (f . g) a, where"+              , "f = " ++ showF+              , "g = " ++ showG+              , "a = " ++ showA+              ]+        , lawContextReduced = reduced lhs rhs+        }+  heqCtx lhs rhs ctx++functorConst ::+  ( Functor f+  , forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)+  ) => (forall x. Gen x -> Gen (f x)) -> Property+functorConst fgen = property $ do+  a <- forAll $ fgen genSmallInteger+  let x = 'X'+  let lhs = fmap (const x) a+  let rhs = x <$ a+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Const", lawContextTcName = "Functor"+        , lawContextLawBody = "fmap (const x)" `congruency` "x <$"+        , lawContextTcProp =+            let showA = show a+                showX = show x+            in lawWhere+              [ "fmap (const x) a" `congruency` "x <$ a, where"+              , "x = " ++ showX+              , "a = " ++ showA+              ]+        , lawContextReduced = reduced lhs rhs+        }+  heqCtx lhs rhs ctx
+ src/Hedgehog/Classes/Generic.hs view
@@ -0,0 +1,110 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE QuantifiedConstraints #-}++module Hedgehog.Classes.Generic (genericLaws) where++import Hedgehog+import Hedgehog.Classes.Common++import GHC.Generics (Generic(..))++-- | Tests the following 'Generic' laws:+--+-- [__From-To Inverse__]: @'from' '.' 'to'@ ≡ @'id'@+-- [__To-From Inverse__]: @'to' '.' 'from'@ ≡ @'id'@+genericLaws ::+  ( Generic a, Eq a, Show a+  , Eq (Rep a x), Show (Rep a x)+  )+  => Gen a+  -> Gen (Rep a x) +  -> Laws+genericLaws gena genr = Laws "Generic"+  [ ("From-To inverse", fromToInverse gena genr)+  , ("To-From inverse", toFromInverse gena genr) +  ]++fromToInverse :: forall a x.+  ( Generic a+  , Eq (Rep a x)+  , Show (Rep a x)+  ) => Gen a -> Gen (Rep a x) -> Property+fromToInverse _gena genr = property $ do+  r <- forAll genr+  let lhs = r+  let rhs = from (to r :: a)+  let ctx = contextualise $ LawContext+        { lawContextLawName = "From-To inverse", lawContextTcName = "Generic"+        , lawContextLawBody = "from . to" `congruency` "id"+        , lawContextTcProp =+            let showR = show r+            in lawWhere+              [ "from . to $ r" `congruency` "id r, where"+              , "r = " ++ showR+              ]+        , lawContextReduced = reduced lhs rhs+        } +  heqCtx lhs rhs ctx++toFromInverse :: forall a x.+  ( Generic a+  , Eq a+  , Show a+  ) => Gen a -> Gen (Rep a x) -> Property+toFromInverse gena _genr = property $ do+  v <- forAll gena+  let lhs = to (from v)+  let rhs = v+  let ctx = contextualise $ LawContext+        { lawContextLawName = "To-From inverse", lawContextTcName = "Generic"+        , lawContextLawBody = "to . from" `congruency` "id"+        , lawContextTcProp =+            let showV = show v+            in lawWhere+              [ "to . from $ v" `congruency` "id v, where"+              , "v = " ++ showV+              ]+        , lawContextReduced = reduced lhs rhs+        } +  heqCtx lhs rhs ctx+       +{-+type Generic1Prop f =+  ( Generic1 f+  , forall x. Eq x => Eq (f x)+  , forall x. Show x => Show (f x)+  , forall x. Eq x => Eq (Rep1 f x)+  , forall x. Show x => Show (Rep1 f x)+  ) => (forall x. Gen x -> Gen (f x))+    -> (forall x. Gen x -> Gen (Rep1 f x))+    -> Property++fromToInverse1 :: forall f. Generic1Prop f+fromToInverse1 _genf genr = property $ do+  r <- forAll $ genr genSmallInteger+  r === (from1 (to1 r :: f Integer))++toFromInverse1 :: forall f. Generic1Prop f+toFromInverse1 genf _genr = property $ do+  v <- forAll $ genf genSmallInteger+  v === (to1 . from1 $ v)+-}++{-+generic1Laws ::+  ( Generic1 f+  , forall x. Eq x => Eq (f x)+  , forall x. Show x => Show (f x)+  , forall x. Eq x => Eq (Rep1 f x)+  , forall x. Show x => Show (Rep1 f x)+  ) => (forall x. Gen x -> Gen (f x))+    -> (forall x. Gen x -> Gen (Rep1 f x))+    -> Laws+generic1Laws genf genr = Laws "Generic1"+  [ ("From1-To1 inverse", fromToInverse1 genf genr)+  , ("To1-From1 inverse", toFromInverse1 genf genr)+  ]+-}
+ src/Hedgehog/Classes/Integral.hs view
@@ -0,0 +1,76 @@+{-# LANGUAGE ScopedTypeVariables #-}++module Hedgehog.Classes.Integral (integralLaws) where++import Hedgehog+import Hedgehog.Classes.Common++-- | Tests the following 'Integral' laws:+--+-- [__Quotient Remainder__]: @'quot' x y '*' y '+' ('rem' x y)@ ≡ @x@+-- [__Division Modulus__]: @('div' x y) '*' y '+' ('mod' x y)@ ≡ @x@+-- [__Integer Roundtrip__]: @'fromInteger' '.' 'toInteger'@ ≡ @'id'@+integralLaws :: (Integral a, Show a) => Gen a -> Laws+integralLaws gen = Laws "Integral"+  [ ("Quotient Remainder", integralQuotientRemainder gen)+  , ("Division Modulus", integralDivisionModulus gen)+  , ("Integer Roundtrip", integralIntegerRoundtrip gen)+  ]++integralQuotientRemainder :: forall a. (Integral a, Show a) => Gen a -> Property+integralQuotientRemainder gen = property $ do+  x <- forAll gen+  y <- forAll gen+  let lhs = (quot x y) * y + (rem x y)+  let rhs = x+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Quotient Remainder", lawContextTcName = "Integral"+        , lawContextLawBody = "quot x y * y + (rem x y)" `congruency` "x"+        , lawContextTcProp =+            let showX = show x; showY = show y;+            in lawWhere+              [ "quot x y * y + (rem x y)" `congruency` "x, where"+              , "x = " ++ showX+              , "y = " ++ showY+              ]+        , lawContextReduced = reduced lhs rhs+        }  +  heqCtx lhs rhs ctx++integralDivisionModulus :: forall a. (Integral a, Show a) => Gen a -> Property+integralDivisionModulus gen = property $ do+  x <- forAll gen+  y <- forAll gen+  let lhs = (div x y) * y + (mod x y)+  let rhs = x+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Division Modulus", lawContextTcName = "Integral"+        , lawContextLawBody = "(div x y) * y + (mod x y)" `congruency` "x"+        , lawContextTcProp =+            let showX = show x; showY = show y;+            in lawWhere+              [ "(div x y) * y + (mod x y)" `congruency` "x, where"+              , "x = " ++ showX+              , "y = " ++ showY+              ]+        , lawContextReduced = reduced lhs rhs+        } +  heqCtx lhs rhs ctx  ++integralIntegerRoundtrip :: forall a. (Integral a, Show a) => Gen a -> Property+integralIntegerRoundtrip gen = property $ do+  x <- forAll gen+  let lhs = fromInteger (toInteger x)+  let rhs = x+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Integer Roundtrip", lawContextTcName = "Integral"+        , lawContextLawBody = "fromInteger . toInteger" `congruency` "id"+        , lawContextTcProp =+            let showX = show x;+            in lawWhere+              [ "fromInteger . toInteger $ x" `congruency` "id x, where"+              , "x = " ++ showX+              ]+        , lawContextReduced = reduced lhs rhs+        }+  heqCtx lhs rhs ctx
+ src/Hedgehog/Classes/Json.hs view
@@ -0,0 +1,64 @@+{-# LANGUAGE ScopedTypeVariables #-}++module Hedgehog.Classes.Json (jsonLaws) where++import Hedgehog+import Hedgehog.Classes.Common+import Data.Aeson (FromJSON, ToJSON(toJSON))+import qualified Data.Aeson as Aeson++-- | Tests the following 'ToJSON' / 'FromJSON' laws:+--+-- [__Encoding Partial Isomorphism__]: @'Aeson.decode' '.' 'Aeson.encode'@ ≡ @'Just'@+-- [__Encoding Equals Value__]: @'Aeson.decode' '.' 'Aeson.encode'@ ≡ @'Just' '.' 'Aeson.toJSON'@+jsonLaws :: (FromJSON a, ToJSON a, Eq a, Show a) => Gen a -> Laws+jsonLaws gen = Laws "ToJSON/FromJSON"+  [ ("Partial Isomorphism", jsonEncodingPartialIsomorphism gen)+  , ("Encoding equals value", jsonEncodingEqualsValue gen)+  ]++jsonEncodingPartialIsomorphism :: forall a. (ToJSON a, FromJSON a, Show a, Eq a) => Gen a -> Property+jsonEncodingPartialIsomorphism gen = property $ do+  x <- forAll gen+  let encoded = Aeson.encode x+  let lhs = Aeson.decode encoded+  let rhs = Just x+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Partial Isomorphism", lawContextTcName = "ToJSON/FromJSON"+        , lawContextLawBody = "decode . encode" `congruency` "Just"+        , lawContextTcProp =+            let showX = show x+                showEncoded = show encoded+            in lawWhere+              [ "decode . encode $ x" `congruency` "Just x, where"+              , "x = " ++ showX+              , "encode x = " ++ showEncoded+              ]+        , lawContextReduced = reduced lhs rhs+        }  +  heqCtx lhs rhs ctx++jsonEncodingEqualsValue :: forall a. (ToJSON a, Show a) => Gen a -> Property+jsonEncodingEqualsValue gen = property $ do+  x <- forAll gen+  let encoded = Aeson.encode x+  let decoded = Aeson.decode encoded :: Maybe Aeson.Value+  let lhs = decoded+  let rhs = Just (toJSON x)+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Encoding equals value", lawContextTcName = "ToJSON"+        , lawContextLawBody = "decode . encode" `congruency` "Just . toJSON"+        , lawContextTcProp =+            let showX = show x+                showEncoded = show encoded+                showDecoded = show decoded+            in lawWhere+              [ "decode . encode $ x" `congruency` "Just . toJSON, where"+              , "x = " ++ showX+              , "encoded = " ++ showEncoded+              , "decoded = " ++ showDecoded+              ]+        , lawContextReduced = reduced lhs rhs +        }+  heqCtx lhs rhs ctx +
+ src/Hedgehog/Classes/Monad.hs view
@@ -0,0 +1,143 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE QuantifiedConstraints #-}+{-# LANGUAGE RankNTypes #-}++module Hedgehog.Classes.Monad (monadLaws) where++import Control.Monad (ap)++import Hedgehog+import Hedgehog.Classes.Common++-- | Tests the following 'Monad' laws:+--+-- [__Left Identity__]: @'return' a '>>=' k@ ≡ @k a@+-- [__Right Identity__]: @m '>>=' 'return'@ ≡ @m@+-- [__Associativity__]: @m '>>=' (\\x -> k x '>>=' h)@ ≡ @(m '>>=' k) '>>=' h@+-- [__Return__]: @'return'@ ≡ @'pure'@+-- [__Ap__]: @'ap' f x@ ≡ @f '<*>' x@+monadLaws ::+  ( Monad f+  , forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)+  ) => (forall x. Gen x -> Gen (f x)) -> Laws+monadLaws gen = Laws "Monad"+  [ ("Left Identity", monadLeftIdentity gen)+  , ("Right Identity", monadRightIdentity gen)+  , ("Associativity", monadAssociativity gen)+  , ("Return", monadReturn gen)+  , ("Ap", monadAp gen)+  ]++type MonadProp f =+  ( Monad f+  , forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)+  ) => (forall x. Gen x -> Gen (f x)) -> Property++monadLeftIdentity :: forall f. MonadProp f+monadLeftIdentity _ = property $ do+  k' :: LinearEquationM f <- forAll genLinearEquationM+  a <- forAll $ genSmallInteger+  let k = runLinearEquationM k'++  let lhs = return a >>= k+  let rhs = k a+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Left Identity", lawContextTcName = "Monad"+        , lawContextLawBody = "return a >>= k" `congruency` "k a"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showK = show k'+                showA = show a+            in lawWhere+              [ "return a >>= k" `congruency` "k a, where"+              , "k = " ++ showK+              , "a = " ++ showA+              ]+        }+  heqCtx1 lhs rhs ctx++monadRightIdentity :: forall f. MonadProp f+monadRightIdentity fgen = property $ do+  m <- forAll $ fgen genSmallInteger+  let lhs = m >>= return+  let rhs = m+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Right Identity", lawContextTcName = "Monad"+        , lawContextLawBody = "m >>= return" `congruency` "m"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showM = show m+            in lawWhere+              [ "m >>= return" `congruency` "m, where"+              , "m = " ++ showM+              ]+        }  +  heqCtx1 lhs rhs ctx++monadAssociativity :: forall f. MonadProp f+monadAssociativity fgen = property $ do+  m <- forAll $ fgen genSmallInteger+  k' :: LinearEquationM f <- forAll genLinearEquationM+  h' :: LinearEquationM f <- forAll genLinearEquationM+  let k = runLinearEquationM k'+      h = runLinearEquationM h'+  let lhs = m >>= (\x -> k x >>= h)+  let rhs = (m >>= k) >>= h+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Associativity", lawContextTcName = "Monad"+        , lawContextLawBody = "m >>= (\\x -> k x >>= h)" `congruency` "(m >>= k) >>= h"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showM = show m+                showK = show k'+                showH = show h'+            in lawWhere+              [ "m >>= (\\x -> k x >>= h)" `congruency` "(m >>= k) >>= h, where"+              , "m = " ++ showM+              , "k = " ++ showK+              , "h = " ++ showH+              ]+        }+  heqCtx1 lhs rhs ctx++monadReturn :: forall f. MonadProp f+monadReturn _ = property $ do+  x <- forAll genSmallInteger+  let lhs = return x+  let rhs = pure x :: f Integer+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Return", lawContextTcName = "Monad"+        , lawContextLawBody = "return" `congruency` "pure"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showX = show x+            in lawWhere+              [ "return x" `congruency` "pure x, where"+              , "x = " ++ showX+              ]+        }  +  heqCtx1 lhs rhs ctx++monadAp :: forall f. MonadProp f+monadAp _ = property $ do+  f' :: f QuadraticEquation <- forAll $ pure <$> genQuadraticEquation+  x :: f Integer <- forAll $ pure <$> genSmallInteger+  let f = fmap runQuadraticEquation f'++  let lhs = ap f x+  let rhs = f <*> x+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Ap", lawContextTcName = "Monad"+        , lawContextLawBody = "ap f" `congruency` "f <*>"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showX = show x+                showF = show f'+            in lawWhere+              [ "ap f x" `congruency` "f <*> x, where"+              , "f = " ++ showF +              , "x = " ++ showX+              ]+        }+  heqCtx1 lhs rhs ctx+
+ src/Hedgehog/Classes/MonadIO.hs view
@@ -0,0 +1,68 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE QuantifiedConstraints #-}+{-# LANGUAGE RankNTypes #-}++module Hedgehog.Classes.MonadIO (monadIOLaws) where++import Control.Monad.IO.Class (MonadIO(..))++import Hedgehog+import Hedgehog.Classes.Common++-- | Tests the following 'MonadIO' laws:+--+-- [__Return__]: @'liftIO' '.' 'return'@ ≡ @'return'@+-- [__Lift__]: @'liftIO' (m '>>=' f)@ ≡ @'liftIO' m '>>=' ('liftIO' '.' f)@+monadIOLaws ::+  ( MonadIO f+  , forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)+  ) => (forall x. Gen x -> Gen (f x)) -> Laws+monadIOLaws gen = Laws "MonadIO"+  [ ("Return", monadIOReturn gen)+  , ("Lift", monadIOLift gen)+  ]++type MonadIOProp f =+  ( MonadIO f+  , forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)+  ) => (forall x. Gen x -> Gen (f x)) -> Property++monadIOReturn :: forall f. MonadIOProp f+monadIOReturn _fgen = property $ do+  x <- forAll genSmallInteger+  let lhs = liftIO (return x)+  let rhs = return x :: f Integer+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Return", lawContextTcName = "MonadIO"+        , lawContextLawBody = "liftIO . return" `congruency` "return"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showX = show x+            in lawWhere+              [ "liftIO . return $ x" `congruency` "return x, where"+              , "x = " ++ showX+              ]+        }+  heqCtx1 lhs rhs ctx++monadIOLift :: forall f. MonadIOProp f+monadIOLift _fgen = property $ do+  m <- forAllWith showIO $ genIO genSmallInteger+  f' <- forAll genLinearEquation+  let f = pure . runLinearEquation f'+  let lhs = liftIO (m >>= f) :: f Integer+  let rhs = liftIO m >>= (liftIO . f) :: f Integer+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Lift", lawContextTcName = "MonadIO"+        , lawContextLawBody = "liftIO (m >>= f)" `congruency` "liftIO m >>= (liftIO . f)"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showM = showIO m+                showF = show f'+            in lawWhere+              [ "liftIO (m >>= f)" `congruency` "liftIO m >>= (liftIO . f), where"+              , "f = " ++ showF+              , "m = " ++ showM+              ]+        }+  heqCtx1 lhs rhs ctx
+ src/Hedgehog/Classes/MonadPlus.hs view
@@ -0,0 +1,134 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE QuantifiedConstraints #-}+{-# LANGUAGE RankNTypes #-}++module Hedgehog.Classes.MonadPlus (monadPlusLaws) where++import Control.Monad (MonadPlus(..))++import Hedgehog+import Hedgehog.Classes.Common++-- | Tests the following 'MonadPlus' laws:+--+-- [__Left Identity__]: @'mplus' 'mzero'@ ≡ @'id'@+-- [__Right Identity__]: @'flip' 'mplus' 'mzero'@ ≡ @'id'@+-- [__Associativity__]: @'mplus' a ('mplus' b c)@ ≡ @'mplus' ('mplus' a b) c@+-- [__Left Zero__]: @'mzero' '>>=' f@ ≡ @'mzero'@+-- [__Right Zero__]: @v '>>' 'mzero'@ ≡ @'mzero'@+monadPlusLaws ::+  ( MonadPlus f+  , forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)+  ) => (forall x. Gen x -> Gen (f x)) -> Laws+monadPlusLaws gen = Laws "Monad"+  [ ("Left Identity", monadPlusLeftIdentity gen)+  , ("Right Identity", monadPlusRightIdentity gen)+  , ("Associativity", monadPlusAssociativity gen)+  , ("Left Zero", monadPlusLeftZero gen)+  , ("Right Zero", monadPlusRightZero gen)+  ]++type MonadPlusProp f =+  ( MonadPlus f+  , forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)+  ) => (forall x. Gen x -> Gen (f x)) -> Property++monadPlusLeftIdentity :: forall f. MonadPlusProp f+monadPlusLeftIdentity fgen = property $ do+  x <- forAll $ fgen genSmallInteger+  let lhs = mplus mzero x+  let rhs = x+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Left Identity", lawContextTcName = "MonadPlus"+        , lawContextLawBody = "mplus mzero" `congruency` "id"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp  =+            let showX = show x; showMZero = show (mzero :: f Integer);+            in lawWhere+              [ "mplus mzero x" `congruency` "id x, where"+              , "x = " ++ showX+              , "mzero = " ++ showMZero+              ]+        }+  heqCtx1 lhs rhs ctx  ++monadPlusRightIdentity :: forall f. MonadPlusProp f+monadPlusRightIdentity fgen = property $ do+  x <- forAll $ fgen genSmallInteger+  let lhs = mplus x mzero+  let rhs = x+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Right Identity", lawContextTcName = "MonadPlus"+        , lawContextLawBody = "flip mplus mzero" `congruency` "id"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp  =+            let showX = show x; showMZero = show (mzero :: f Integer);+            in lawWhere+              [ "mplus x mzero" `congruency` "id x, where"+              , "x = " ++ showX+              , "mzero = " ++ showMZero+              ]+        } +  heqCtx1 lhs rhs ctx  ++monadPlusAssociativity :: forall f. MonadPlusProp f+monadPlusAssociativity fgen = property $ do+  a <- forAll $ fgen genSmallInteger+  b <- forAll $ fgen genSmallInteger+  c <- forAll $ fgen genSmallInteger+  let lhs = mplus a (mplus b c)+  let rhs = mplus (mplus a b) c+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Associativity", lawContextTcName = "MonadPlus"+        , lawContextLawBody = "mplus a (mplus b c)" `congruency` "mplus (mplus a b) c"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showA = show a; showB = show b; showC = show c;+            in lawWhere+              [ "mplus a (mplus b c)" `congruency` "mplus (mplus a b) c, where"+              , "a = " ++ showA+              , "b = " ++ showB+              , "c = " ++ showC+              ]+        }+  heqCtx1 lhs rhs ctx ++monadPlusLeftZero :: forall f. MonadPlusProp f+monadPlusLeftZero _ = property $ do+  k' :: LinearEquationM f <- forAll genLinearEquationM+  let lhs = mzero >>= runLinearEquationM k'+  let rhs = mzero+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Left Zero", lawContextTcName = "MonadPlus"+        , lawContextLawBody = "mzero >>= f" `congruency` "mzero"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp  =+            let showF = show k'; showMZero = show (mzero :: f Integer);+            in lawWhere+              [ "mzero >>= f" `congruency` "mzero, where"+              , "f = " ++ showF+              , "mzero = " ++ showMZero+              ]+        }+  heqCtx1 lhs rhs ctx++monadPlusRightZero :: forall f. MonadPlusProp f+monadPlusRightZero fgen = property $ do+  v <- forAll $ fgen genSmallInteger+  let lhs = v >> (mzero :: f Integer)+  let rhs = mzero+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Right Zero", lawContextTcName = "MonadPlus"+        , lawContextLawBody = "v >> mzero" `congruency` "mzero"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp  =+            let showV = show v; showMZero = show (mzero :: f Integer);+            in lawWhere+              [ "v >> mzero" `congruency` "mzero, where"+              , "v = " ++ showV+              , "mzero = " ++ showMZero+              ]+        } +  heqCtx1 lhs rhs ctx   ++
+ src/Hedgehog/Classes/MonadZip.hs view
@@ -0,0 +1,53 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE QuantifiedConstraints #-}+{-# LANGUAGE RankNTypes #-}++module Hedgehog.Classes.MonadZip (monadZipLaws) where++import Control.Arrow (Arrow(..))+import Control.Monad.Zip (MonadZip(mzip))++import Hedgehog+import Hedgehog.Classes.Common++-- | Tests the following 'MonadZip' laws:+--+-- [__Naturality__]: @'fmap' (f '***' g) ('mzip' ma mb)@ ≡ @'mzip' ('fmap' f ma) ('fmap' g mb)@+monadZipLaws ::+  ( MonadZip f+  , forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)+  ) => (forall x. Gen x -> Gen (f x)) -> Laws+monadZipLaws gen = Laws "Monad"+  [ ("Naturality", monadZipNaturality gen)+  ]++type MonadZipProp f =+  ( MonadZip f+  , forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)+  ) => (forall x. Gen x -> Gen (f x)) -> Property++monadZipNaturality :: forall f. MonadZipProp f+monadZipNaturality fgen = property $ do+  f' <- forAll genLinearEquation+  g' <- forAll genLinearEquation+  let f = runLinearEquation f'+      g = runLinearEquation g'+  ma <- forAll $ fgen genSmallInteger+  mb <- forAll $ fgen genSmallInteger+  let lhs = fmap (f *** g) (mzip ma mb)+  let rhs = mzip (fmap f ma) (fmap g mb)+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Naturality", lawContextTcName = "MonadZip"+        , lawContextLawBody = "(fmap (f *** g) (mzip ma mb)" `congruency` "mzip (fmap f ma) (fmap g mb)"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showF = show f'; showG = show g'; showMA = show ma; showMB = show mb;+            in lawWhere+              [ "fmap (f *** g) (mzip ma mb)" `congruency` "mzip (fmap f ma) (fmap g mb), where"+              , "f = " ++ showF+              , "g = " ++ showG+              , "ma = " ++ showMA  +              , "mb = " ++ showMB+              ]+        }+  heqCtx1 lhs rhs ctx
+ src/Hedgehog/Classes/Monoid.hs view
@@ -0,0 +1,127 @@+{-# LANGUAGE ScopedTypeVariables #-}++module Hedgehog.Classes.Monoid (monoidLaws, commutativeMonoidLaws) where++import Hedgehog+import Hedgehog.Classes.Common++-- | Tests the following 'Monoid' laws:+--+-- [__Left Identity__]: @'mappend' 'mempty'@ ≡ @'id'@+-- [__Right Identity__]: @'flip' 'mappend' 'mempty'@ ≡ @'id'@+-- [__Associativity__]: @'mappend' a ('mappend' b c)@ ≡ @'mappend' ('mappend' a b) c@+-- [__Concatenation__]: @'mconcat'@ ≡ @'foldr' 'mappend' 'mempty'@+monoidLaws :: (Eq a, Monoid a, Show a) => Gen a -> Laws+monoidLaws gen = Laws "Monoid"+  [ ("Left Identity", monoidLeftIdentity gen)+  , ("Right Identity", monoidRightIdentity gen)+  , ("Associativity", monoidAssociative gen)+  , ("Concatenation", monoidConcatenation gen)+  ]++-- | Tests the following 'Monoid' laws:+--+-- [__Commutativity__]: @'mappend' a b@ ≡ @'mappend' b a@+commutativeMonoidLaws :: (Eq a, Monoid a, Show a) => Gen a -> Laws+commutativeMonoidLaws gen = Laws "Commutative Monoid"+  [ ("Commutativity", monoidCommutative gen)+  ]++monoidConcatenation :: forall a. (Eq a, Monoid a, Show a) => Gen a -> Property+monoidConcatenation gen = property $ do+  as <- forAll $ genSmallList gen+  let lhs = mconcat as+  let rhs = foldr mappend mempty as+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Concatenation", lawContextTcName = "Monoid"+        , lawContextLawBody = "mconcat" `congruency` "foldr mappend mempty"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showAS = show as; showMempty = show (mempty :: a);+            in lawWhere+              [ "mconcat as" `congruency` "foldr mappend mempty as, where"+              , "as = " ++ showAS+              , "mempty = " ++ showMempty+              ]+        }  +  heqCtx lhs rhs ctx++monoidAssociative :: forall a. (Eq a, Monoid a, Show a) => Gen a -> Property+monoidAssociative gen = property $ do+  a <- forAll gen+  b <- forAll gen+  c <- forAll gen+  let lhs = mappend a (mappend b c)+  let rhs = mappend (mappend a b) c+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Associativity", lawContextTcName = "Monoid"+        , lawContextLawBody = "mappend a (mappend b c)" `congruency` "mappend (mappend a b) c"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showA = show a; showB = show b; showC = show c;+            in lawWhere+              [ "mappend a (mappend b c)" `congruency` "mappend (mappend a b) c, where"+              , "a = " ++ showA+              , "b = " ++ showB+              , "c = " ++ showC+              ]+        }+  heqCtx lhs rhs ctx++monoidLeftIdentity :: forall a. (Eq a, Monoid a, Show a) => Gen a -> Property+monoidLeftIdentity gen = property $ do+  a <- forAll gen+  let lhs = mappend mempty a+  let rhs = a+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Left Identity", lawContextTcName = "Monoid"+        , lawContextLawBody = "mappend mempty" `congruency` "id"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showA = show a; showMempty = show (mempty :: a);+            in lawWhere+              [ "mappend mempty a" `congruency` "a, where"+              , "a = " ++ showA+              , "mempty = " ++ showMempty+              ]+        }+  heqCtx lhs rhs ctx++monoidRightIdentity :: forall a. (Eq a, Monoid a, Show a) => Gen a -> Property+monoidRightIdentity gen = property $ do+  a <- forAll gen+  let lhs = mappend a mempty+  let rhs = a +  let ctx = contextualise $ LawContext+        { lawContextLawName = "Right Identity", lawContextTcName = "Monoid"+        , lawContextLawBody = "flip mappend mempty" `congruency` "id"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showA = show a; showMempty = show (mempty :: a);+            in lawWhere+              [ "mappend a mempty" `congruency` "a, where"+              , "a = " ++ showA+              , "mempty = " ++ showMempty+              ]+        }+  heqCtx lhs rhs ctx ++monoidCommutative :: forall a. (Eq a, Monoid a, Show a) => Gen a -> Property+monoidCommutative gen = property $ do+  a <- forAll gen+  b <- forAll gen+  let lhs = mappend a b+  let rhs = mappend b a+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Commutativity", lawContextTcName = "Monoid (Commutative)"+        , lawContextLawBody = "mappend" `congruency` "flip mappend"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showA = show a; showB = show b;+            in lawWhere+              [ "mappend a b" `congruency` "mappend b a, where"+              , "a = " ++ showA+              , "b = " ++ showB+              ]+        }+  heqCtx lhs rhs ctx
+ src/Hedgehog/Classes/Ord.hs view
@@ -0,0 +1,113 @@+{-# LANGUAGE ScopedTypeVariables #-}++module Hedgehog.Classes.Ord (ordLaws) where++import Hedgehog+import Hedgehog.Classes.Common++-- | Tests the following 'Ord' laws:+--+-- [__Antisymmetry__]: @@ ≡ @@+-- [__Transitivity__]: @@ ≡ @@+-- [__Reflexivity__]: @@ ≡ @@+-- [__Totality__]: @@ ≡ @@+ordLaws :: forall a. (Ord a, Show a) => Gen a -> Laws+ordLaws gen = Laws "Ord"+  [ ("Antisymmetry", ordAntisymmetric gen)+  , ("Transitivity", ordTransitive gen)+  , ("Reflexivity", ordReflexive gen)+  , ("Totality", ordTotal gen) +  ]++ordAntisymmetric :: forall a. (Ord a, Show a) => Gen a -> Property+ordAntisymmetric gen = property $ do+  a <- forAll gen+  b <- forAll gen+  let lhs = (a <= b) && (b <= a)+  let rhs = a == b+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Antisymmetry", lawContextTcName = "Ord"+        , lawContextLawBody = "x <= y && y <= x" `congruency` "x == y"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showA = show a; showB = show b;+            in lawWhere+              [ "x <= y && y <= x" `congruency` "x == y, where"+              , "x = " ++ showA +              , "y = " ++ showB+              ]+        } +  heqCtx lhs rhs ctx++ordTransitive :: forall a. (Ord a, Show a) => Gen a -> Property+ordTransitive gen = property $ do+  x <- forAll gen+  y <- forAll gen+  z <- forAll gen+  let lhs = x <= y && y <= z+  let rhs = x <= z+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Transitivity", lawContextTcName = "Ord"+        , lawContextLawBody = "x <= y && y <= z" `congruency` "x <= z"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showX = show x; showY = show y; showZ = show z;+            in lawWhere+              [ "x <= y && y <= z" `congruency` "x <= z, where"+              , "x = " ++ showX+              , "y = " ++ showY+              , "z = " ++ showZ+              ]+        }+  heqCtx lhs rhs ctx++{-+  case (compare a b, compare b c) of+    (LT,LT) -> a `hLessThan` c+    (LT,EQ) -> a `hLessThan` c+    (LT,GT) -> success+    (EQ,LT) -> a `hLessThan` c+    (EQ,EQ) -> a === c+    (EQ,GT) -> a `hGreaterThan` c+    (GT,LT) -> success+    (GT,EQ) -> a `hGreaterThan` c+    (GT,GT) -> a `hGreaterThan` c+-}++ordTotal :: forall a. (Ord a, Show a) => Gen a -> Property+ordTotal gen = property $ do+  a <- forAll gen+  b <- forAll gen+  let lhs = (a <= b) || (b <= a)+  let rhs = True+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Totality", lawContextTcName = "Ord"+        , lawContextLawBody = "x <= y || y <= x" `congruency` "True"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showA = show a; showB = show b;+            in lawWhere+              [ "(x <= y) || (y <= x)" `congruency` "True, where"+              , "x = " ++ showA+              , "y = " ++ showB+              ]+        }+  heqCtx lhs rhs ctx++ordReflexive :: forall a. (Ord a, Show a) => Gen a -> Property+ordReflexive gen = property $ do+  x <- forAll gen+  let lhs = x <= x+  let rhs = True+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Reflexivity", lawContextTcName = "Ord"+        , lawContextLawBody = "x <= x" `congruency` "True"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showX = show x;+            in lawWhere+              [ "x <= x" `congruency` "True, where"+              , "x = " ++ showX+              ]+        }+  heqCtx lhs rhs ctx
+ src/Hedgehog/Classes/Semigroup.hs view
@@ -0,0 +1,203 @@+{-# LANGUAGE ScopedTypeVariables #-}++module Hedgehog.Classes.Semigroup+  ( semigroupLaws+  , commutativeSemigroupLaws+  , exponentialSemigroupLaws+  , idempotentSemigroupLaws+  , rectangularBandSemigroupLaws+  ) where++import Data.Semigroup (Semigroup(..))+import Hedgehog+import Hedgehog.Classes.Common+import Data.List.NonEmpty+import qualified Hedgehog.Gen as Gen+import qualified Hedgehog.Range as Range+import qualified Data.Foldable as Foldable++-- | Tests the following 'Semigroup' laws:+--+-- [__Associativity__]: @@ ≡ @@+-- [__Concatenation__]: @@ ≡ @@+-- [__Times__]: @@ ≡ @@+semigroupLaws :: (Eq a, Semigroup a, Show a) => Gen a -> Laws+semigroupLaws gen = Laws "Semigroup"+  [ ("Associativity", semigroupAssociative gen)+  , ("Concatenation", semigroupConcatenation gen)+  , ("Times", semigroupTimes gen)+  ]++-- | Tests the following 'Semigroup' laws:+--+-- [__Commutativity__]: @@ ≡ @@+commutativeSemigroupLaws :: (Eq a, Semigroup a, Show a) => Gen a -> Laws+commutativeSemigroupLaws gen = Laws "Commutative Semigroup"+  [ ("Commutative", semigroupCommutative gen)+  ]++-- | Tests the following 'Semigroup' laws:+--+-- [__Exponential__]: @@ ≡ @@+exponentialSemigroupLaws :: (Eq a, Semigroup a, Show a) => Gen a -> Laws+exponentialSemigroupLaws gen = Laws "Exponential Semigroup"+  [ ("Exponential", semigroupExponential gen)+  ]++-- | Tests the following 'Semigroup' laws:+--+-- [__Idempotent__]: @@ ≡ @@+idempotentSemigroupLaws :: (Eq a, Semigroup a, Show a) => Gen a -> Laws+idempotentSemigroupLaws gen = Laws "Idempotent Semigroup"+  [ ("Idempotent", semigroupIdempotent gen)+  ]++-- | Tests the following 'Semigroup' laws:+--+-- [__Rectangular Band__]: @@ ≡ @@+rectangularBandSemigroupLaws :: (Eq a, Semigroup a, Show a) => Gen a -> Laws+rectangularBandSemigroupLaws gen = Laws "Rectangular Band Semigroup"+  [ ("Rectangular Band", semigroupRectangularBand gen)+  ]++semigroupAssociative :: forall a. (Eq a, Semigroup a, Show a) => Gen a -> Property+semigroupAssociative gen = property $ do+  a <- forAll gen+  b <- forAll gen+  c <- forAll gen+  let lhs = a <> (b <> c)+  let rhs = (a <> b) <> c+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Associativity", lawContextTcName = "Semigroup"+        , lawContextLawBody = "a <> (b <> c)" `congruency` "(a <> b) <> c"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showA = show a; showB = show b; showC = show c;+            in lawWhere+              [ "a <> (b <> c)" `congruency` "(a <> b) <> c, where"+              , "a = " ++ showA+              , "b = " ++ showB+              , "c = " ++ showC+              ]+        }+  heqCtx lhs rhs ctx++semigroupCommutative :: forall a. (Eq a, Semigroup a, Show a) => Gen a -> Property+semigroupCommutative gen = property $ do+  a <- forAll gen+  b <- forAll gen+  let lhs = a <> b+  let rhs = b <> a+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Commutativity", lawContextTcName = "Semigroup"+        , lawContextLawBody = "a <> b" `congruency` "b <> a"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showA = show a; showB = show b;+            in lawWhere+              [ "a <> b" `congruency` "b <> a, where"+              , "a = " ++ showA+              , "b = " ++ showB+              ]+        }  +  heqCtx lhs rhs ctx++semigroupConcatenation :: forall a. (Eq a, Semigroup a, Show a) => Gen a -> Property+semigroupConcatenation gen = property $ do+  a <- forAll gen +  as <- forAll $ genSmallList gen+  let ne = a :| as+  let lhs = sconcat ne+  let rhs = Foldable.foldr1 (<>) ne+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Concatenation", lawContextTcName = "Semigroup"+        , lawContextLawBody = "sconcat" `congruency` "foldr1 (<>)"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showNE = show ne;+            in lawWhere+              [ "sconcat ne" `congruency` "foldr1 (<>) ne, where"+              , "ne = " ++ showNE+              ]+        }+  heqCtx lhs rhs ctx  ++semigroupTimes :: forall a. (Eq a, Semigroup a, Show a) => Gen a -> Property+semigroupTimes gen = property $ do+  a <- forAll gen+  n <- forAll (Gen.int Range.constantBounded)+  let lhs = stimes n a+  let rhs = Foldable.foldr1 (<>) (replicate n a)+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Times", lawContextTcName = "Semigroup"+        , lawContextLawBody = "stimes" `congruency` "(foldr1 (<>) .) . replicate"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showN = show n; showA = show a;+            in lawWhere+              [ "stimes n a" `congruency` "foldr1 (<>) (replicate n a), where"+              , "a = " ++ showA+              , "n = " ++ showN+              ]+        }  +  heqCtx lhs rhs ctx++semigroupExponential :: forall a. (Eq a, Semigroup a, Show a) => Gen a -> Property+semigroupExponential gen = property $ do+  a <- forAll gen+  b <- forAll gen+  n <- forAll (Gen.int Range.constantBounded)+  let lhs = stimes n (a <> b)+  let rhs = stimes n a <> stimes n b+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Exponential", lawContextTcName = "Semigroup"+        , lawContextLawBody = "stimes n (a <> b)" `congruency` "stimes n a <> stimes n b"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showN = show n; showA = show a; showB = show b;+            in lawWhere+              [ "stimes n (a <> b)" `congruency` "stimes n a <> stimes n b, where"+              , "a = " ++ showA+              , "b = " ++ showB+              , "n = " ++ showN+              ]+        }  +  heqCtx lhs rhs ctx++semigroupIdempotent :: forall a. (Eq a, Semigroup a, Show a) => Gen a -> Property+semigroupIdempotent gen = property $ do+  a <- forAll gen+  let lhs = a <> a+  let rhs = a+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Idempotency", lawContextTcName = "Semigroup"+        , lawContextLawBody = "a <> a" `congruency` "a"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showA = show a;+            in lawWhere+              [ "a <> a" `congruency` "a, where"+              , "a = " ++ showA+              ]+        }+  heqCtx lhs rhs ctx++semigroupRectangularBand :: forall a. (Eq a, Semigroup a, Show a) => Gen a -> Property+semigroupRectangularBand gen = property $ do+  a <- forAll gen+  b <- forAll gen+  let lhs = a <> b <> a+  let rhs = a+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Rectangular Band", lawContextTcName = "Semigroup"+        , lawContextLawBody = "a <> b <> a" `congruency` "a"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showA = show a; showB = show b;+            in lawWhere+              [ "a <> b <> a" `congruency` "a, where"+              , "a = " ++ showA+              , "b = " ++ showB+              ]+        }  +  heqCtx lhs rhs ctx
+ src/Hedgehog/Classes/Show.hs view
@@ -0,0 +1,82 @@+{-# LANGUAGE ScopedTypeVariables #-}++module Hedgehog.Classes.Show (showLaws) where++import Hedgehog+import Hedgehog.Classes.Common++-- | Tests the following 'Show' laws:+--+-- [__ __]: @@ ≡ @@+-- [__ __]: @@ ≡ @@+-- [__ __]: @@ ≡ @@+showLaws :: (Show a) => Gen a -> Laws+showLaws gen = Laws "Show"+  [ ("Show", showShowsPrecZero gen)+  , ("Equivariance: showsPrec", equivarianceShowsPrec gen)+  , ("Equivariance: showList", equivarianceShowList gen)+  ]++showShowsPrecZero :: forall a. (Show a) => Gen a -> Property+showShowsPrecZero gen = property $ do+  a <- forAll gen+  let lhs = show a+  let rhs = showsPrec 0 a ""+  let ctx = contextualise $ LawContext+        { lawContextLawName = "ShowsPrec Zero", lawContextTcName = "Show"+        , lawContextLawBody = "show a" `congruency` "showsPrec 0 a \"\""+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showA = show a;+            in lawWhere+              [ "show a" `congruency` "showsPrec 0 a \"\", where"+              , "a = " ++ showA+              ]+        }  +  heqCtx lhs rhs ctx++equivarianceShowsPrec :: forall a. (Show a) => Gen a -> Property+equivarianceShowsPrec gen = property $ do+  p <- forAll genShowReadPrecedence+  a <- forAll gen+  r <- forAll genSmallString+  s <- forAll genSmallString+  let lhs = showsPrec p a r ++ s+  let rhs = showsPrec p a (r ++ s)+  let ctx = contextualise $ LawContext+        { lawContextLawName = "ShowsPrec Equivariance", lawContextTcName = "Show"+        , lawContextLawBody = "showsPrec p a r ++ s" `congruency` "showsPrec p a (r ++ s)"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showP = show p; showA = show a; showR = show r; showS = show s;+            in lawWhere+              [ "showsPrec p a r ++ s" `congruency` "showsPrec p a (r ++ s), where"+              , "p = " ++ showP+              , "a = " ++ showA+              , "r = " ++ showR+              , "s = " ++ showS+              ]+        }  +  heqCtx lhs rhs ctx++equivarianceShowList :: forall a. (Show a) => Gen a -> Property+equivarianceShowList gen = property $ do+  as <- forAll $ genSmallList gen+  r <- forAll genSmallString+  s <- forAll genSmallString+  let lhs = showList as r ++ s+  let rhs = showList as (r ++ s)+  let ctx = contextualise $ LawContext+        { lawContextLawName = "ShowList Equivariance", lawContextTcName = "Show"+        , lawContextLawBody = "showList as r ++ s" `congruency` "showList as (r ++ s)"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showAS = show as; showR = show r; showS = show s;+            in lawWhere+              [ "showList as r ++ s" `congruency` "showList as (r ++ s), where"+              , "as = " ++ showAS+              , "r = " ++ showR+              , "s = " ++ showS+              ]+        }  +  heqCtx lhs rhs ctx
+ src/Hedgehog/Classes/ShowRead.hs view
@@ -0,0 +1,116 @@+{-# LANGUAGE ScopedTypeVariables #-}++module Hedgehog.Classes.ShowRead (showReadLaws) where++import Hedgehog+import Hedgehog.Classes.Common++import Text.Read (readListDefault, readMaybe)+import Text.Show (showListWith)++-- | Tests the following 'Show' / 'Read' laws:+--+-- [__ __]: @@ ≡ @@+-- [__ __]: @@ ≡ @@+-- [__ __]: @@ ≡ @@+showReadLaws :: (Eq a, Read a, Show a) => Gen a -> Laws+showReadLaws gen = Laws "Show/Read"+  [ ("Partial Isomorphism: show/read", showReadPartialIsomorphism gen)+  , ("Partial Isomorphism: show/read with initial space", showReadSpacePartialIsomorphism gen)+  , ("Partial Isomorphism: showsPrec/readsPrec", showsPrecReadsPrecPartialIsomorphism gen)+  , ("Partial Isomorphism: showList/readList", showListReadListPartialIsomorphism gen)+  , ("Partial Isomorphism: showListWith shows / readListDefault", showListWithShowsReadListDefaultPartialIsomorphism gen)+  ]++showReadPartialIsomorphism :: forall a. (Eq a, Read a, Show a) => Gen a -> Property+showReadPartialIsomorphism gen = property $ do+  a <- forAll gen+  let lhs = readMaybe (show a)+  let rhs = Just a+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Show/Read Partial Isomorphism", lawContextTcName = "Show/Read"+        , lawContextLawBody = "readMaybe . show" `congruency` "Just"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showA = show a;+            in lawWhere+              [ "readMaybe . show $ a" `congruency` "Just a, where"+              , "a = " ++ showA+              ]+        } +  heqCtx lhs rhs ctx++showReadSpacePartialIsomorphism :: forall a. (Eq a, Read a, Show a) => Gen a -> Property+showReadSpacePartialIsomorphism gen = property $ do+  a <- forAll gen+  let lhs = readMaybe (" " ++ show a)+  let rhs = Just a+  let ctx = contextualise $ LawContext+        { lawContextLawName = "Show/Read Partial Isomorphism With Initial Space", lawContextTcName = "Show/Read"+        , lawContextLawBody = "readMaybe . (\" \" ++ show)" `congruency` "Just"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showA = show a;+            in lawWhere+              [ "readMaybe . (\" \" ++ show) $ a" `congruency` "Just a, where"+              , "a = " ++ showA+              ]+        }+  heqCtx lhs rhs ctx++showsPrecReadsPrecPartialIsomorphism :: forall a. (Eq a, Read a, Show a) => Gen a -> Property+showsPrecReadsPrecPartialIsomorphism gen = property $ do+  a <- forAll gen+  p <- forAll genShowReadPrecedence+  let lhs = (a,"") `elem` readsPrec p (showsPrec p a "")+  let rhs = True+  let ctx = contextualise $ LawContext+        { lawContextLawName = "ShowsPrec/ReadsPrec partial isomorphism", lawContextTcName = "Show/Read"+        , lawContextLawBody = "(a,\"\") `elem` readsPrec p (showsPrec p a \"\")" `congruency` "True"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showA = show a; showP = show p+            in lawWhere+              [ "(a,\"\") `elem` readsPrec p (showsPrec p a \"\")" `congruency` "True, where"+              , "a = " ++ showA+              , "p = " ++ showP+              ]+        }  +  heqCtx lhs rhs ctx++showListReadListPartialIsomorphism :: forall a. (Eq a, Read a, Show a) => Gen a -> Property+showListReadListPartialIsomorphism gen = property $ do+  as <- forAll $ genSmallList gen+  let lhs = (as,"") `elem` readList (showList as "")+  let rhs = True+  let ctx = contextualise $ LawContext+        { lawContextLawName = "ShowsList/ReadsList partial isomorphism", lawContextTcName = "Show/Read"+        , lawContextLawBody = "(as,\"\") `elem` readList (showList as \"\")" `congruency` "True"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showAS = show as+            in lawWhere+              [ "(as,\"\") `elem` readList (showList as \"\")" `congruency` "True, where"+              , "as = " ++ showAS+              ]+        }  +  heqCtx lhs rhs ctx+ +showListWithShowsReadListDefaultPartialIsomorphism :: forall a. (Eq a, Read a, Show a) => Gen a -> Property+showListWithShowsReadListDefaultPartialIsomorphism gen = property $ do+  as <- forAll $ genSmallList gen+  let lhs = (as,"") `elem` readListDefault (showListWith shows as "")+  let rhs = True+  let ctx = contextualise $ LawContext+        { lawContextLawName = "ShowListWith/ReadListDefault partial isomorphism", lawContextTcName = "Show/Read"+        , lawContextLawBody = "(as,\"\") `elem` readListDefault (showListWith shows as \"\")" `congruency` "True"+        , lawContextReduced = reduced lhs rhs+        , lawContextTcProp =+            let showAS = show as+            in lawWhere+              [ "(as,\"\") `elem` readListDefault (showListWith shows as \"\")" `congruency` "True, where"+              , "as = " ++ showAS +              ]+        } +  heqCtx lhs rhs ctx+
+ src/Hedgehog/Classes/Storable.hs view
@@ -0,0 +1,150 @@+{-# LANGUAGE ScopedTypeVariables #-}++module Hedgehog.Classes.Storable (storableLaws) where++import Hedgehog+import Hedgehog.Classes.Common+import Hedgehog.Internal.Gen (sample)++import qualified Data.List as List+import qualified Hedgehog.Gen as Gen+import qualified Hedgehog.Range as Range++import Foreign.Marshal.Alloc+import Foreign.Marshal.Array+import GHC.Ptr (Ptr(..), plusPtr)+import Foreign.Storable (Storable(..))+import System.IO.Unsafe (unsafePerformIO)++-- | Tests the following 'Storable' laws:+--+-- [__ __]: @@ ≡ @@+-- [__ __]: @@ ≡ @@+-- [__ __]: @@ ≡ @@+storableLaws :: (Eq a, Show a, Storable a) => Gen a -> Laws+storableLaws gen = Laws "Storable"+  [ ("Set-Get (you get back what you put in)", storableSetGet gen)+  , ("Get-Set (putting back what you got out has no effect)", storableGetSet gen)+  , ("List Conversion Roundtrips", storableList gen)+  , ("peekElemOff a i ≡ peek (plusPtr a (i * sizeOf undefined))", storablePeekElem gen)+  , ("peekElemOff a i x ≡ poke (plusPtr a (i * sizeOf undefined)) x ≡ id ", storablePokeElem gen)+  , ("peekByteOff a i ≡ peek (plusPtr a i)", storablePeekByte gen)+  , ("peekByteOff a i x ≡ poke (plusPtr a i) x ≡ id ", storablePokeByte gen)+  ]++genArray :: forall a. (Storable a) => Gen a -> Int -> IO (Ptr a)+genArray gen len = do+  let go ix xs = if ix == len+        then pure xs+        else do+          x <- sample gen+          go (ix + 1) (x : xs)+  as <- go 0 []+  newArray as++storablePeekElem :: forall a. (Eq a, Show a, Storable a) => Gen a -> Property+storablePeekElem gen = property $ do+  as <- forAll $ genSmallNonEmptyList gen+  let len = List.length as+  ix <- forAll $ Gen.int (Range.linear 0 (len - 1))+  unsafePerformIO $ do+    addr <- genArray gen len+    x <- peekElemOff addr ix+    y <- peek (addr `plusPtr` (ix * sizeOf (undefined :: a)))+    free addr+    pure (x === y)++storablePokeElem :: forall a. (Eq a, Show a, Storable a) => Gen a -> Property+storablePokeElem gen = property $ do+  as <- forAll $ genSmallNonEmptyList gen+  x <- forAll gen+  let len = List.length as+  ix <- forAll $ Gen.int (Range.linear 0 (len - 1))+  unsafePerformIO $ do+    addr <- genArray gen len+    pokeElemOff addr ix x+    u <- peekElemOff addr ix+    poke (addr `plusPtr` (ix * sizeOf x)) x+    v <- peekElemOff addr ix+    free addr+    pure (u === v)++storablePeekByte :: forall a. (Eq a, Show a, Storable a) => Gen a -> Property+storablePeekByte gen = property $ do+  as <- forAll $ genSmallNonEmptyList gen+  let len = List.length as+  off <- forAll $ Gen.int (Range.linear 0 (len - 1))+  unsafePerformIO $ do+    addr <- genArray gen len+    x :: a <- peekByteOff addr off+    y :: a <- peek (addr `plusPtr` off)+    free addr+    pure (x === y)++storablePokeByte :: forall a. (Eq a, Show a, Storable a) => Gen a -> Property+storablePokeByte gen = property $ do+  as <- forAll $ genSmallNonEmptyList gen+  x <- forAll gen+  let len = List.length as+  off <- forAll $ Gen.int (Range.linear 0 (len - 1))+  unsafePerformIO $ do+    addr <- genArray gen len+    pokeByteOff addr off x+    u :: a <- peekByteOff addr off+    poke (addr `plusPtr` off) x+    v :: a <- peekByteOff addr off+    free addr+    pure (u === v)++storableSetGet :: forall a. (Eq a, Show a, Storable a) => Gen a -> Property+storableSetGet gen = property $ do+  a <- forAll gen+  len <- forAll $ Gen.int (Range.linear 0 20)+  ix <- forAll $ Gen.int (Range.linear 0 (len - 1))+  unsafePerformIO $ do+    ptr <- genArray gen len+    pokeElemOff ptr ix a+    a' <- peekElemOff ptr ix+    free ptr+    pure (a === a')++storableGetSet :: forall a. (Eq a, Show a, Storable a) => Gen a -> Property+storableGetSet gen = property $ do+  as <- forAll $ genSmallNonEmptyList gen+  let len = List.length as+  ix <- forAll $ Gen.int (Range.linear 0 (len - 1))+  unsafePerformIO $ do+    ptrA <- newArray as+    ptrB <- genArray gen len+    copyArray ptrB ptrA len+    a <- peekElemOff ptrA ix+    pokeElemOff ptrA ix a+    res <- arrayEq ptrA ptrB len+    free ptrA+    free ptrB+    pure (res === True)++storableList :: forall a. (Eq a, Show a, Storable a) => Gen a -> Property+storableList gen = property $ do+  as <- forAll $ genSmallNonEmptyList gen +  unsafePerformIO $ do+    let len = List.length as+    ptr <- newArray as+    let rebuild :: Int -> IO [a]+        rebuild ix = if ix < len+          then (:) <$> peekElemOff ptr ix <*> rebuild (ix + 1)+          else pure []+    asNew <- rebuild 0+    free ptr+    pure (as === asNew)++arrayEq :: forall a. (Eq a, Storable a) => Ptr a -> Ptr a -> Int -> IO Bool+arrayEq ptrA ptrB len = go 0 where+  go i = if i < len+    then do+      a <- peekElemOff ptrA i+      b <- peekElemOff ptrB i+      if a == b+        then go (i + 1)+        else pure False+    else pure True
+ src/Hedgehog/Classes/Traversable.hs view
@@ -0,0 +1,88 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE QuantifiedConstraints #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE LambdaCase #-}++module Hedgehog.Classes.Traversable (traversableLaws) where++import Hedgehog+import Hedgehog.Classes.Common++import Data.Functor.Identity+import Data.Functor.Compose+import Data.Traversable (Traversable(..), foldMapDefault, fmapDefault)++-- | Tests the following 'Traversable' laws:+--+-- [__Naturality__]: @t '.' 'traverse' f@ ≡ @'traverse' (t '.' f), for every applicative transformation t@+-- [__Identity__]: @'traverse' 'Identity'@ ≡ @'Identity'@+-- [__Composition__]: @'traverse' ('Compose' '.' 'fmap' g '.' f)@ ≡ @'Compose' '.' 'fmap' ('traverse' g) '.' 'traverse' f@+-- [__SequenceA Naturality__]: @t '.' 'sequenceA'@ ≡ @'sequenceA' '.' 'fmap' t, for every applicative transformation t@+-- [__SequenceA Identity__]: @'sequenceA' '.' 'fmap' 'Identity'@ ≡ @'Identity'@+-- [__SequenceA Composition__]: @'sequenceA' '.' 'fmap' 'Compose'@ ≡ @'Compose' '.' 'fmap' 'sequenceA' '.' 'sequenceA'@+-- [__FoldMap__]: @'foldMap'@ ≡ @'foldMapDefault'@+-- [__Fmap__]: @'fmap'@ ≡ @'fmapDefault'@+traversableLaws ::+  ( Traversable f+  , forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)+  ) => (forall x. Gen x -> Gen (f x)) -> Laws+traversableLaws gen = Laws "Foldable"+  [ ("Naturality", traversableNaturality gen)+  , ("Identity", traversableIdentity gen)+  , ("Composition", traversableComposition gen)+  , ("Sequence Naturality", traversableSequenceNaturality gen)+  , ("Sequence Identity", traversableSequenceIdentity gen)+  , ("Sequence Composition", traversableSequenceComposition gen)+  , ("foldMap", traversableFoldMap gen)+  , ("fmap", traversableFmap gen)+  ]++type TraversableProp f =+  ( Traversable f+  , forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)+  ) => (forall x. Gen x -> Gen (f x)) -> Property++traversableNaturality :: TraversableProp f+traversableNaturality fgen = property $ do+  a <- forAll $ fgen genSmallInteger+  (apTrans (traverse func4 a)) `heq1` (traverse (apTrans . func4) a)++traversableIdentity :: TraversableProp f+traversableIdentity fgen = property $ do+  t <- forAll $ fgen genSmallInteger+  (traverse Identity t) `heq1` (Identity t)++traversableComposition :: TraversableProp f+traversableComposition fgen = property $ do+  t <- forAll $ fgen genSmallInteger +  let lhs = (traverse (Compose . fmap func5 . func6) t)+  let rhs = (Compose (fmap (traverse func5) (traverse func6 t)))+  lhs `heq1` rhs++traversableSequenceNaturality :: TraversableProp f+traversableSequenceNaturality fgen = property $ do+  x <- forAll $ fgen (genCompose genSmallInteger genTriple (genTuple genSetInteger))+  let a = fmap toSpecialApplicative x+  (apTrans (sequenceA a)) `heq1` (sequenceA (fmap apTrans a)) ++traversableSequenceIdentity :: TraversableProp f+traversableSequenceIdentity fgen = property $ do+  t <- forAll $ fgen genSmallInteger+  (sequenceA (fmap Identity t)) `heq1` (Identity t)++traversableSequenceComposition :: TraversableProp f+traversableSequenceComposition fgen = property $ do+  let genTripleInteger = genTriple genSmallInteger+  t <- forAll $ fgen (genTriple genTripleInteger)+  (sequenceA (fmap Compose t)) `heq1` (Compose (fmap sequenceA (sequenceA t)))++traversableFoldMap :: TraversableProp f+traversableFoldMap fgen = property $ do+  t <- forAll $ fgen genSmallInteger+  foldMap func3 t `heq1` foldMapDefault func3 t  ++traversableFmap :: TraversableProp f+traversableFmap fgen = property $ do+  t <- forAll $ fgen genSmallInteger+  fmap func3 t `heq1` fmapDefault func3 t+