hedgehog-classes-0.2.5.4: Hedgehog will eat your typeclass bugs

Safe Haskell | None
Language | Haskell2010

Hedgehog.Classes

Contents

- Running
- Properties
  - Ground types
  - Unary type constructors
  - Binary type constructors
- Defining your own `Laws`
- Hedgehog equality tests sans source information

Description

This library provides sets of properties that should hold for common typeclasses.

Note: functions that test laws of a subclass never test the laws of a superclass. For example, `commutativeSemigroupLaws` never tests the laws provided by `semigroupLaws`.

Synopsis

- lawsCheck :: Laws -> IO Bool
- lawsCheckOne :: Gen a -> [Gen a -> Laws] -> IO Bool
- lawsCheckMany :: [(String, [Laws])] -> IO Bool
- binaryLaws :: (Binary a, Eq a, Show a) => Gen a -> Laws
- bitsLaws :: (FiniteBits a, Show a) => Gen a -> Laws
- eqLaws :: (Eq a, Show a) => Gen a -> Laws
- integralLaws :: (Integral a, Show a) => Gen a -> Laws
- monoidLaws :: (Eq a, Monoid a, Show a) => Gen a -> Laws
- commutativeMonoidLaws :: (Eq a, Monoid a, Show a) => Gen a -> Laws
- ordLaws :: (Ord a, Show a) => Gen a -> Laws
- enumLaws :: (Enum a, Eq a, Show a) => Gen a -> Laws
- boundedEnumLaws :: (Bounded a, Enum a, Eq a, Show a) => Gen a -> Laws
- semigroupLaws :: (Eq a, Semigroup a, Show a) => Gen a -> Laws
- commutativeSemigroupLaws :: (Eq a, Semigroup a, Show a) => Gen a -> Laws
- exponentialSemigroupLaws :: (Eq a, Semigroup a, Show a) => Gen a -> Laws
- idempotentSemigroupLaws :: (Eq a, Semigroup a, Show a) => Gen a -> Laws
- rectangularBandSemigroupLaws :: (Eq a, Semigroup a, Show a) => Gen a -> Laws
- jsonLaws :: (FromJSON a, ToJSON a, Eq a, Show a) => Gen a -> Laws
- genericLaws :: (Generic a, Eq a, Show a, Eq (Rep a x), Show (Rep a x)) => Gen a -> Gen (Rep a x) -> Laws
- primLaws :: (Prim a, Eq a, Show a) => Gen a -> Laws
- semiringLaws :: (Semiring a, Eq a, Show a) => Gen a -> Laws
- ringLaws :: (Ring a, Eq a, Show a) => Gen a -> Laws
- starLaws :: (Star a, Eq a, Show a) => Gen a -> Laws
- showLaws :: Show a => Gen a -> Laws
- showReadLaws :: (Eq a, Read a, Show a) => Gen a -> Laws
- storableLaws :: (Eq a, Show a, Storable a) => Gen a -> Laws
- muvectorLaws :: (Eq a, Unbox a, Show a) => Gen a -> Laws
- 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
- 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
- comonadLaws :: (Comonad f, forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)) => (forall x. Gen x -> Gen (f x)) -> Laws
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- arrowLaws :: (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
- bifoldableLaws :: (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
- bifoldableFunctorLaws :: (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
- bifunctorLaws :: (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
- bitraversableLaws :: (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
- categoryLaws :: (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 :: (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
- data Laws = Laws {
  - lawsTypeClass :: String
  - lawsProperties :: [(String, Property)]
  }
- data LawContext = LawContext {
  - lawContextLawName :: String
  - lawContextLawBody :: String
  - lawContextTcName :: String
  - lawContextTcProp :: String
  - lawContextReduced :: String
  }
- data Context
  - = NoContext
  - | Context String
- contextualise :: LawContext -> Context
- hLessThan :: (MonadTest m, Ord a, Show a, HasCallStack) => a -> a -> m ()
- hGreaterThan :: (MonadTest m, Ord a, Show a, HasCallStack) => a -> a -> m ()
- heq :: (MonadTest m, HasCallStack, Eq a, Show a) => a -> a -> m ()
- heq1 :: (MonadTest m, HasCallStack, Eq a, Show a, forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)) => f a -> f a -> m ()
- heq2 :: (MonadTest m, HasCallStack, Eq a, Eq b, Show a, Show b, forall x y. (Eq x, Eq y) => Eq (f x y), forall x y. (Show x, Show y) => Show (f x y)) => f a b -> f a b -> m ()
- heqCtx :: (MonadTest m, HasCallStack, Eq a, Show a) => a -> a -> Context -> m ()
- heqCtx1 :: (MonadTest m, HasCallStack, Eq a, Show a, forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)) => f a -> f a -> Context -> m ()
- heqCtx2 :: (MonadTest m, HasCallStack, Eq a, Eq b, Show a, Show b, forall x y. (Eq x, Eq y) => Eq (f x y), forall x y. (Show x, Show y) => Show (f x y)) => f a b -> f a b -> Context -> m ()
- hneq :: (MonadTest m, HasCallStack, Eq a, Show a) => a -> a -> m ()
- hneq1 :: (MonadTest m, HasCallStack, Eq a, Show a, forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)) => f a -> f a -> m ()
- hneq2 :: (MonadTest m, HasCallStack, Eq a, Eq b, Show a, Show b, forall x y. (Eq x, Eq y) => Eq (f x y), forall x y. (Show x, Show y) => Show (f x y)) => f a b -> f a b -> m ()
- hneqCtx :: (MonadTest m, HasCallStack, Eq a, Show a) => a -> a -> Context -> m ()
- hneqCtx1 :: (MonadTest m, HasCallStack, Eq a, Show a, forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)) => f a -> f a -> Context -> m ()
- hneqCtx2 :: (MonadTest m, HasCallStack, Eq a, Eq b, Show a, Show b, forall x y. (Eq x, Eq y) => Eq (f x y), forall x y. (Show x, Show y) => Show (f x y)) => f a b -> f a b -> Context -> m ()

# Running

lawsCheck Source #

Arguments

:: Laws | The `Laws` you would like to check.
-> IO Bool | `True` if your tests pass, `False` otherwise.

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)
    Monoid: Left Identity    ✓ <interactive> passed 100 tests.
    Monoid: Right Identity    ✓ <interactive> passed 100 tests.
    Monoid: Associativity    ✓ <interactive> passed 100 tests.
    Monoid: Concatenation    ✓ <interactive> passed 100 tests.
    True

lawsCheckOne Source #

Arguments

:: 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.

A convenience function for testing many typeclass instances of a single type.

    >>> lawsCheckOne (word8 constantBounded) [jsonLaws, showReadLaws]
    ToJSON/FromJSON: Partial Isomorphism    ✓ <interactive> passed 100 tests.
    ToJSON/FromJSON: Encoding equals value    ✓ <interactive> passed 100 tests.
    Show/Read: Partial Isomorphism: show/read    ✓ <interactive> passed 100 tests.
    Show/Read: Partial Isomorphism: show/read with initial space    ✓ <interactive> passed 100 tests.
    Show/Read: Partial Isomorphism: showsPrec/readsPrec    ✓ <interactive> passed 100 tests.
    Show/Read: Partial Isomorphism: showList/readList    ✓ <interactive> passed 100 tests.
    Show/Read: Partial Isomorphism: showListWith shows/readListDefault    ✓ <interactive> passed 100 tests.
    True

lawsCheckMany Source #

Arguments

:: [(String, [Laws])] | Pairs of type names and their associated laws to test.
-> IO Bool | `True` if your tests pass. `False` otherwise.

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 --
    -------------

    Eq: Transitive   ✓ interactive passed 100 tests.
    Eq: Symmetric   ✓ interactive passed 100 tests.
    Eq: Reflexive   ✓ interactive passed 100 tests.
    Eq: Negation   ✓ interactive passed 100 tests.
    Monoid: Left Identity   ✓ interactive passed 100 tests.
    Monoid: Right Identity   ✓ interactive passed 100 tests.
    Monoid: Associativity   ✓ interactive passed 100 tests.
    Monoid: Concatenation   ✓ interactive passed 100 tests.

    --------------------
    -- Map String Int --
    --------------------

    Eq: Transitive   ✓ interactive passed 100 tests.
    Eq: Symmetric   ✓ interactive passed 100 tests.
    Eq: Reflexive   ✓ interactive passed 100 tests.
    Eq: Negation   ✓ interactive passed 100 tests.
    Monoid: Left Identity   ✓ interactive passed 100 tests.
    Monoid: Right Identity   ✓ interactive passed 100 tests.
    Monoid: Associativity   ✓ interactive passed 100 tests.
    Monoid: Concatenation   ✓ interactive passed 100 tests.

    All tests succeeded
    True

# Properties

## Ground types

binaryLaws :: (Binary a, Eq a, Show a) => Gen a -> Laws Source #

Tests the following `Binary` laws:

Encoding Partial Isomorphism
  ``decode` `.` `encode`` ≡ ``id``

bitsLaws :: (FiniteBits a, Show a) => Gen a -> Laws Source #

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)`

eqLaws :: (Eq a, Show a) => Gen a -> Laws Source #

Tests the following `Eq` laws:

Reflexivity
  `x `==` x` ≡ ``True``
Symmetry
  `x `==` y` ≡ `y `==` x`
Transitivity
  `x `==` y `&&` y `==` z` ≡ `x `==` z`
Negation
  `x `/=` y` ≡ ``not` (x `==` y)`

integralLaws :: (Integral a, Show a) => Gen a -> Laws Source #

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``

monoidLaws :: (Eq a, Monoid a, Show a) => Gen a -> Laws Source #

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``

commutativeMonoidLaws :: (Eq a, Monoid a, Show a) => Gen a -> Laws Source #

Tests the following `Monoid` laws:

Commutativity
  ``mappend` a b` ≡ ``mappend` b a`

ordLaws :: (Ord a, Show a) => Gen a -> Laws Source #

Tests the following `Ord` laws:

Antisymmetry
  `x `<=` y `&&` y `<=` x` ≡ `x `==` y`
Transitivity
  `x `<=` y `&&` y `<=` z` ≡ `x `<=` z`
Reflexivity
  `x `<=` x` ≡ ``True``
Totality
  `x `<=` y `||` y `<=` x` ≡ ``True``

enumLaws :: (Enum a, Eq a, Show a) => Gen a -> Laws Source #

Tests the following `Enum` laws:

Succ-Pred Identity
  ``succ` `.` `pred`` ≡ ``id``
Pred-Succ Identity
  ``pred` `.` `succ`` ≡ ``id``

boundedEnumLaws :: (Bounded a, Enum a, Eq a, Show a) => Gen a -> Laws Source #

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.

semigroupLaws :: (Eq a, Semigroup a, Show a) => Gen a -> Laws Source #

Tests the following `Semigroup` laws:

Associativity
  `a `<>` (b `<>` c)` ≡ `(a `<>` b) `<>` c`
Concatenation
  ``sconcat`` ≡ ``foldr1` (`<>`)`
Times
  ``stimes` n a` ≡ ``foldr1` (`<>`) (`replicate` n a)`

commutativeSemigroupLaws :: (Eq a, Semigroup a, Show a) => Gen a -> Laws Source #

Tests the following `Semigroup` laws:

Commutativity
  `a `<>` b` ≡ `b `<>` a`

exponentialSemigroupLaws :: (Eq a, Semigroup a, Show a) => Gen a -> Laws Source #

Tests the following `Semigroup` laws:

Exponentiality
  ``stimes` n (a `<>` b)` ≡ ``stimes` n a `<>` `stimes` n b`

idempotentSemigroupLaws :: (Eq a, Semigroup a, Show a) => Gen a -> Laws Source #

Tests the following `Semigroup` laws:

Idempotency
  `a `<>` a` ≡ `a`

rectangularBandSemigroupLaws :: (Eq a, Semigroup a, Show a) => Gen a -> Laws Source #

Tests the following `Semigroup` laws:

Rectangular Bandedness
  `a `<>` b `<>` a` ≡ `a`

jsonLaws :: (FromJSON a, ToJSON a, Eq a, Show a) => Gen a -> Laws Source #

Tests the following `ToJSON` / `FromJSON` laws:

Encoding Partial Isomorphism
  ``decode` `.` `encode`` ≡ ``Just``
Encoding Equals Value
  ``decode` `.` `encode`` ≡ ``Just` `.` `toJSON``

genericLaws :: (Generic a, Eq a, Show a, Eq (Rep a x), Show (Rep a x)) => Gen a -> Gen (Rep a x) -> Laws Source #

Tests the following `Generic` laws:

From-To Inverse
  ``from` `.` `to`` ≡ ``id``
To-From Inverse
  ``to` `.` `from`` ≡ ``id``

primLaws :: (Prim a, Eq a, Show a) => Gen a -> Laws Source #

Tests the following `Prim` laws:

ByteArray Set-Get
  ``primitive_` (`writeByteArray#` ba# ix# x) `*>` `primitive` (`readByteArray#` ba# ix#)` ≡ ``pure` x`
ByteArray Get-Set
  ``primitive` (`readByteArray#` ba# ix#) `>>=` x -> `primitive_` (`writeByteArray#` ba# ix# x)` ≡ ``pure` ()`
ByteArray Set-Set
  ``primitive_` (`writeByteArray#` ba# ix# x) *> `primitive_` (`writeByteArray#` ba# ix# x)` ≡ ``primitive_` (`writeByteArray#` ba# ix# x)`
ByteArray Set Range
  The behavior of `setByteArray#` matches the default implementation
ByteArray List Conversion Roundtrips
  Turning a list into a `PrimArray` and back gives you the same list
Addr Set-Get
  ``primitive_` (`writeOffAddr#` addr# ix# x) `*>` `primitive` (`readOffAddr#` addr# ix#)` ≡ ``pure` x`
Addr Get-Set
  ``primitive` (`readOffAddr#` addr# ix#) `>>=` x -> `primitive_` (`writeOffAddr#` addr# ix# x)` ≡ ``pure` ()`
Addr Set-Set
  ``primitive_` (`writeOffAddr#` addr# ix# x) `*>` `primitive_` (`writeOffAddr#` addr# ix# x)` ≡ ``primitive_` (`writeOffAddr#` addr# ix# x)`
Addr Set Range
  The behavior of `setOffAddr#` matches the default implementation
Addr List Conversion Roundtrips
  Mallocing a list and then reconstructing it gives you the same list

semiringLaws :: (Semiring a, Eq a, Show a) => Gen a -> Laws Source #

Tests the following `Semiring` laws:

Additive Left Identity
  ``zero` `+` x` ≡ `x`
Additive Right Identity
  `x `+` `zero`` ≡ `x`
Additive Associativity
  `x `+` (y `+` z)` ≡ `(x `+` y) `+` z`
Additive Commutativity
  `x `+` y` ≡ `y `+` x`
Multiplicative Left Identity
  ``one` `*` x` ≡ `x`
Multiplicative Right Identity
  `x `*` `one`` ≡ `x`
Multiplicative Associativity
  `x `*` (y `*` z)` ≡ `(x `*` y) `*` z`
Multiplicatiion Left-Distributes Over Addtion
  `x `*` (y `+` z)` ≡ `(x `*` y) `+` (x `*` z)`
Multiplication Right-Distibutes Over Addition
  `(y `+` z) `*` x` ≡ `(y `*` x) `+` (z `*` x)`
Multiplicative Left Annihilation
  ``zero` `*` x` ≡ ``zero``
Multiplicative Right Annihilation
  `x `*` `zero`` ≡ ``zero``

ringLaws :: (Ring a, Eq a, Show a) => Gen a -> Laws Source #

Tests the following `Ring` laws:

Additive Inverse
  ``negate` x `+` x` ≡ ``zero``

starLaws :: (Star a, Eq a, Show a) => Gen a -> Laws Source #

Tests the following `Star` laws:

Asteration
  ``star` x` ≡ ``one` `+` x `*` `star` x`
APlus
  ``aplus` x` ≡ `x `*` `star` x`

showLaws :: Show a => Gen a -> Laws Source #

Tests the following `Show` laws:

ShowsPrec Zero
  ``show` a` ≡ ``showsPrec` 0 a ""`
ShowsPrec Equivariance
  ``showsPrec` p a r `++` s` ≡ `'showsPrec p a (r `++` s)`
ShowsPrec ShowList
  ``showList` as r `++` s` ≡ ``showList` as (r `++` s)`

showReadLaws :: (Eq a, Read a, Show a) => Gen a -> Laws Source #

Tests the following `Show` / `Read` laws:

Partial Isomorphism: show/read
  ``readMaybe` `.` `show`` ≡ ``Just``
Partial Isomorphism: show/read with initial space
  ``readMaybe` `.` (" " `++`) `.` `show`` ≡ ``Just``
Partial Isomorphism: showsPrec/readPrec
  `(a,"") `elem` `readsPrec` p (`showsPrec` p a "")` ≡ ``True``
Partial Isomorphism: showList/readList
  `(as,"") `elem` `readList` (`showList` as "")` ≡ ``True``
Partial Isomorphism: showListWith shows/readListDefault
  `(as,"") `elem` `readListDefault` (`showListWith` `shows` as "")` ≡ ``True``

storableLaws :: (Eq a, Show a, Storable a) => Gen a -> Laws Source #

Tests the following `Storable` laws:

Set-Get
  ``pokeElemOff` ptr ix a `>>` `peekElemOff` ptr ix` ≡ ``pure` a`
Get-Set
  ``peekElemOff` ptr ix `>>=` `pokeElemOff` ptr ix` ≡ ``pure` ()` (Putting back what you got out has no effect)
List Conversion Roundtrips
  Mallocing a list and then reconstructing it gives you the same list
PeekElemOff/Peek
  ``peekElemOff` a i` ≡ ``peek` (`plusPtr` a (i `*` `sizeOf` `undefined`))`
PokeElemOff/Poke
  ``pokeElemOff` a i x` ≡ ``poke` (`plusPtr` a (i `*` `sizeOf` `undefined`)) x`
PeekByteOff/Peek
  ``peekByteOff` a i` ≡ ``peek` (`plusPtr` a i)`
PokeByteOff/Peek
  ``pokeByteOff` a i x` ≡ ``poke` (`plusPtr` a i) x`

muvectorLaws :: (Eq a, Unbox a, Show a) => Gen a -> Laws Source #

Test that a `MVector` instance obey several laws.

## Unary type constructors

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 Source #

Tests the following `Alternative` laws:

Left Identity
  ``empty` `<|>` a` ≡ `a`
Right Identity
  `a `<|>` `empty`` ≡ `a`
Associativity
  `a `<|>` (b `<|>` c)` ≡ `(a `<|>` b) `<|>` c`

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 Source #

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`

comonadLaws :: (Comonad f, forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)) => (forall x. Gen x -> Gen (f x)) -> Laws Source #

Tests the following `Comonad` laws:

Extend/Extract Identity
  ``extend` `extract` ≡ `id``
Extract/Extend
  ``extract` `.` `extend` f ≡ f`
Extend/Extend
  ``extend` f `.` `extend` g ≡ `extend` (f `.` `extend` g)`
Extract Right Identity
  `f `=>=` `extract` ≡ f`
Extract Left Identity
  ``extract` `=>=` f ≡ f`
Cokleisli Associativity
  `(f `=>=` g) `=>=` h ≡ f `=>=` (g `=>=` h)`
Extract/Duplicate Identity
  ``extract` `.` `duplicate` ≡ `id``
Fmap Extract/Duplicate Identity
  ``fmap` `extract` `.` `duplicate` ≡ `id``
Double Duplication
  ``duplicate` `.` `duplicate` ≡ `fmap` `duplicate` `.` `duplicate``
Extend/Fmap . Duplicate Identity
  ``extend` f ≡ `fmap` f `.` `duplicate``
Duplicate/Extend id Identity
  ``duplicate` ≡ `extend` `id``
Fmap/Extend Extract
  ``fmap` f ≡ `extend` (f `.` `extract`)`
Fmap/LiftW Isomorphism
  ``fmap` ≡ `liftW``

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 Source #

Tests the following `Contravariant` laws:

Identity
  ``contramap` `id`` ≡ ``id``
Composition
  ``contramap` f `.` `contramap` g` ≡ ``contramap` (g `.` f)`

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 Source #

Tests the following `Foldable` laws:

Fold
  ``fold` ≡ `foldMap` `id``
FoldMap
  ``foldMap` f ≡ `foldr` (`mappend` `.` f) `mempty``
Foldr
  ``foldr` f z t ≡ `appEndo` (`foldMap` (`Endo` `.` f) t) z`
Foldr'
  ``foldr'` f z0 t ≡ `foldl` f' `id` t z0, where f' k x z = k `$!` f x z`
Foldl
  ``foldl` f z t ≡ `appEndo` (`getDual` (`foldMap` (`Dual` `.` `Endo` `.` `flip` f) t)) z`
Foldl'
  ``foldl'` f z0 xs ≡ `foldr` f' `id` xs z0, where f' x k z = k `$!` f z x`
Foldl1
  ``foldl1` f t ≡ let (x:xs) = `toList` t in `foldl` f x xs`
Foldr1
  ``foldr1` f t ≡ let (xs,x)` = `unsnoc (`toList` t) in `foldr` f x xs`
ToList
  ``toList` ≡ `foldr` (:) []`
Null
  ``null` ≡ `foldr` (`const` (`const` `False`)) `True``
Length
  ``length` ≡ `getSum` `.` `foldMap` (`const` (`Sum` 1))`

This additionally tests that the user's implementations of `foldr'` and `foldl'` are strict in their accumulators.

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 Source #

Tests the following `Functor` laws:

Identity
  ``fmap` `id`` ≡ ``id``
Composition
  ``fmap` f `.` `fmap` g` ≡ ``fmap` (f `.` g)`
Const
  ``fmap` (`const` x)` ≡ `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 Source #

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`

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 Source #

Tests the following `MonadIO` laws:

Return
  ``liftIO` `.` `return`` ≡ ``return``
Lift
  ``liftIO` (m `>>=` f)` ≡ ``liftIO` m `>>=` (`liftIO` `.` f)`

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 Source #

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``

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 Source #

Tests the following `MonadZip` laws:

Naturality
  ``fmap` (f `***` g) (`mzip` ma mb)` ≡ ``mzip` (`fmap` f ma) (`fmap` g mb)`

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 Source #

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``

## Binary type constructors

arrowLaws :: (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 Source #

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))`

bifoldableLaws :: (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 Source #

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`

bifoldableFunctorLaws :: (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 Source #

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)`

bifunctorLaws :: (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 Source #

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``

bitraversableLaws :: (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 Source #

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)`

categoryLaws :: (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 Source #

Tests the following `Category` laws:

Left Identity
  ``id` `.` f` ≡ `f`
Right Identity
  `f `.` `id`` ≡ `f`
Associativity
  `f `.` (g `.` h)` ≡ `(f `.` g) `.` h`

commutativeCategoryLaws :: (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 Source #

Tests the following `Category` laws:

Commutativity
  `f `.` g` ≡ `g `.` f`

# Defining your own `Laws`

data Laws Source #

A `Laws` is the name of the typeclass and the set of named properties associated with that typeclass.

Constructors

Laws |

Fields

- lawsTypeClass :: String
- lawsProperties :: [(String, Property)]

data LawContext Source #

The context surrounding the property test of a law. Use `contextualise` to turn this into a `Context`.

Constructors

LawContext |

Fields

- 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

data Context Source #

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.

Constructors

NoContext |
Context String |

contextualise :: LawContext -> Context Source #

Turn a `LawContext` into a `Context`.

# Hedgehog equality tests sans source information

hLessThan :: (MonadTest m, Ord a, Show a, HasCallStack) => a -> a -> m () Source #

Fails the test if the right argument is less 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 () Source #

Fails the test if the right argument is greater than or equal to the left. see https://github.com/hedgehogqa/haskell-hedgehog/pull/196

heq :: (MonadTest m, HasCallStack, Eq a, Show a) => a -> a -> m () infix 4 Source #

Passes the test if the given arguments are equal. Otherwise fails with `NoContext`.

heq1 :: (MonadTest m, HasCallStack, Eq a, Show a, forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)) => f a -> f a -> m () infix 4 Source #

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, forall x y. (Eq x, Eq y) => Eq (f x y), forall x y. (Show x, Show y) => Show (f x y)) => f a b -> f a b -> m () infix 4 Source #

Passes the test if the given arguments are equal. Otherwise fails with `NoContext`.

heqCtx :: (MonadTest m, HasCallStack, Eq a, Show a) => a -> a -> Context -> m () Source #

Passes the test if the given arguments are equal. Otherwise fails with the given `Context`.

heqCtx1 :: (MonadTest m, HasCallStack, Eq a, Show a, forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)) => f a -> f a -> Context -> m () Source #

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, forall x y. (Eq x, Eq y) => Eq (f x y), forall x y. (Show x, Show y) => Show (f x y)) => f a b -> f a b -> Context -> m () Source #

Passes the test if the given arguments are equal. Otherwise fails with the given `Context`.

hneq :: (MonadTest m, HasCallStack, Eq a, Show a) => a -> a -> m () infix 4 Source #

Passes the test if the given arguments are not equal. Otherwise fails with `NoContext`.

hneq1 :: (MonadTest m, HasCallStack, Eq a, Show a, forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)) => f a -> f a -> m () Source #

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, forall x y. (Eq x, Eq y) => Eq (f x y), forall x y. (Show x, Show y) => Show (f x y)) => f a b -> f a b -> m () infix 4 Source #

Passes the test if the given arguments are not equal. Otherwise fails with `NoContext`.

hneqCtx :: (MonadTest m, HasCallStack, Eq a, Show a) => a -> a -> Context -> m () Source #

Passes the test if the given arguments are not equal. Otherwise fails with the given `Context`.

hneqCtx1 :: (MonadTest m, HasCallStack, Eq a, Show a, forall x. Eq x => Eq (f x), forall x. Show x => Show (f x)) => f a -> f a -> Context -> m () Source #

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, forall x y. (Eq x, Eq y) => Eq (f x y), forall x y. (Show x, Show y) => Show (f x y)) => f a b -> f a b -> Context -> m () Source #

Passes the test if the given arguments are not equal. Otherwise fails with the given `Context`.