quickcheck-classes-0.6.5.0: QuickCheck common typeclasses

Safe Haskell | None
Language | Haskell2010

Test.QuickCheck.Classes

Contents

- Running
- Properties
  - Ground types
  - Unary type constructors
  - Binary type constructors
- Types

Description

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

Note: on GHC < 8.6, this library uses the higher-kinded typeclasses (`Show1`, `Eq1`, `Ord1`, etc.), but on GHC >= 8.6, it uses `-XQuantifiedConstraints` to express these constraints more cleanly.

Synopsis

- lawsCheck :: Laws -> IO ()
- lawsCheckMany :: [(String, [Laws])] -> IO ()
- lawsCheckOne :: Proxy a -> [Proxy a -> Laws] -> IO ()
- bitsLaws :: (FiniteBits a, Arbitrary a, Show a) => Proxy a -> Laws
- eqLaws :: (Eq a, Arbitrary a, Show a) => Proxy a -> Laws
- substitutiveEqLaws :: (Eq a, Arbitrary a, CoArbitrary a, Function a, Show a) => Proxy a -> Laws
- numLaws :: (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Laws
- integralLaws :: (Integral a, Arbitrary a, Show a) => Proxy a -> Laws
- ixLaws :: (Ix a, Arbitrary a, Show a) => Proxy a -> Laws
- isListLaws :: (IsList a, Show a, Show (Item a), Arbitrary a, Arbitrary (Item a), Eq a) => Proxy a -> Laws
- jsonLaws :: (ToJSON a, FromJSON a, Show a, Arbitrary a, Eq a) => Proxy a -> Laws
- monoidLaws :: (Monoid a, Eq a, Arbitrary a, Show a) => Proxy a -> Laws
- commutativeMonoidLaws :: (Monoid a, Eq a, Arbitrary a, Show a) => Proxy a -> Laws
- semigroupMonoidLaws :: (Semigroup a, Monoid a, Eq a, Arbitrary a, Show a) => Proxy a -> Laws
- ordLaws :: (Ord a, Arbitrary a, Show a) => Proxy a -> Laws
- enumLaws :: (Enum a, Eq a, Arbitrary a, Show a) => Proxy a -> Laws
- boundedEnumLaws :: (Enum a, Bounded a, Eq a, Arbitrary a, Show a) => Proxy a -> Laws
- primLaws :: (Prim a, Eq a, Arbitrary a, Show a) => Proxy a -> Laws
- semigroupLaws :: (Semigroup a, Eq a, Arbitrary a, Show a) => Proxy a -> Laws
- commutativeSemigroupLaws :: (Semigroup a, Eq a, Arbitrary a, Show a) => Proxy a -> Laws
- exponentialSemigroupLaws :: (Semigroup a, Eq a, Arbitrary a, Show a) => Proxy a -> Laws
- idempotentSemigroupLaws :: (Semigroup a, Eq a, Arbitrary a, Show a) => Proxy a -> Laws
- rectangularBandSemigroupLaws :: (Semigroup a, Eq a, Arbitrary a, Show a) => Proxy a -> Laws
- semiringLaws :: (Semiring a, Eq a, Arbitrary a, Show a) => Proxy a -> Laws
- ringLaws :: (Ring a, Eq a, Arbitrary a, Show a) => Proxy a -> Laws
- gcdDomainLaws :: (Eq a, GcdDomain a, Arbitrary a, Show a) => Proxy a -> Laws
- euclideanLaws :: (Eq a, Euclidean a, Arbitrary a, Show a) => Proxy a -> Laws
- showLaws :: (Show a, Arbitrary a) => Proxy a -> Laws
- showReadLaws :: (Show a, Read a, Eq a, Arbitrary a) => Proxy a -> Laws
- storableLaws :: (Storable a, Eq a, Arbitrary a, Show a) => Proxy a -> Laws
- genericLaws :: (Generic a, Eq a, Arbitrary a, Show a, Show (Rep a ()), Arbitrary (Rep a ()), Eq (Rep a ())) => Proxy a -> Laws
- generic1Laws :: forall (f :: Type -> Type) proxy. (Generic1 f, Eq1 f, Arbitrary1 f, Show1 f, Eq1 (Rep1 f), Show1 (Rep1 f), Arbitrary1 (Rep1 f)) => proxy f -> Laws
- alternativeLaws :: forall (f :: Type -> Type) proxy. (Alternative f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => proxy f -> Laws
- altLaws :: forall proxy (f :: Type -> Type). (Alt f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => proxy f -> Laws
- applyLaws :: forall (f :: Type -> Type) proxy. (Apply f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => proxy f -> Laws
- applicativeLaws :: forall (f :: Type -> Type) proxy. (Applicative f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => proxy f -> Laws
- contravariantLaws :: forall (f :: Type -> Type) proxy. (Contravariant f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => proxy f -> Laws
- foldableLaws :: forall proxy (f :: Type -> Type). (Foldable f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => proxy f -> Laws
- functorLaws :: forall (f :: Type -> Type) proxy. (Functor f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => proxy f -> Laws
- monadLaws :: forall (f :: Type -> Type) proxy. (Monad f, Applicative f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => proxy f -> Laws
- monadPlusLaws :: forall (f :: Type -> Type) proxy. (MonadPlus f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => proxy f -> Laws
- monadZipLaws :: forall (f :: Type -> Type) proxy. (MonadZip f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => proxy f -> Laws
- plusLaws :: forall proxy (f :: Type -> Type). (Plus f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => proxy f -> Laws
- extendedPlusLaws :: forall proxy (f :: Type -> Type). (Plus f, Alternative f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => proxy f -> Laws
- traversableLaws :: forall (f :: Type -> Type) proxy. (Traversable f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => proxy f -> Laws
- bifoldableLaws :: forall proxy (f :: Type -> Type -> Type). (Bifoldable f, forall a b. (Eq a, Eq b) => Eq (f a b), forall a b. (Show a, Show b) => Show (f a b), forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (f a b)) => proxy f -> Laws
- bifunctorLaws :: forall proxy (f :: Type -> Type -> Type). (Bifunctor f, forall a b. (Eq a, Eq b) => Eq (f a b), forall a b. (Show a, Show b) => Show (f a b), forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (f a b)) => proxy f -> Laws
- bitraversableLaws :: forall proxy (f :: Type -> Type -> Type). (Bitraversable f, forall a b. (Eq a, Eq b) => Eq (f a b), forall a b. (Show a, Show b) => Show (f a b), forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (f a b)) => proxy f -> Laws
- categoryLaws :: forall proxy (c :: Type -> Type -> Type). (Category c, forall a b. (Eq a, Eq b) => Eq (c a b), forall a b. (Show a, Show b) => Show (c a b), forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (c a b)) => proxy c -> Laws
- commutativeCategoryLaws :: forall proxy (c :: Type -> Type -> Type). (Category c, forall a b. (Eq a, Eq b) => Eq (c a b), forall a b. (Show a, Show b) => Show (c a b), forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (c a b)) => proxy c -> Laws
- semigroupoidLaws :: forall proxy (s :: Type -> Type -> Type). (Semigroupoid s, forall a b. (Eq a, Eq b) => Eq (s a b), forall a b. (Show a, Show b) => Show (s a b), forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (s a b)) => proxy s -> Laws
- commutativeSemigroupoidLaws :: forall proxy (s :: Type -> Type -> Type). (Semigroupoid s, forall a b. (Eq a, Eq b) => Eq (s a b), forall a b. (Show a, Show b) => Show (s a b), forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (s a b)) => proxy s -> Laws
- muvectorLaws :: (Eq a, Unbox a, Arbitrary a, Show a) => Proxy a -> Laws
- data Laws = Laws {
  - lawsTypeclass :: String
  - lawsProperties :: [(String, Property)]
  }
- data Proxy1 (f :: Type -> Type) = Proxy1
- data Proxy2 (f :: Type -> Type -> Type) = Proxy2

# Running

lawsCheck :: Laws -> IO () Source #

A convenience function for testing properties in GHCi. For example, at GHCi:

    >>> lawsCheck (monoidLaws (Proxy :: Proxy Ordering))
    Monoid: Associative +++ OK, passed 100 tests.
    Monoid: Left Identity +++ OK, passed 100 tests.
    Monoid: Right Identity +++ OK, passed 100 tests.

Assuming that the `Arbitrary` instance for `Ordering` is good, we now have confidence that the `Monoid` instance for `Ordering` satisfies the monoid laws.

lawsCheckMany Source #

Arguments

:: [(String, [Laws])] | Element is type name paired with typeclass laws
-> IO () |

A convenience function for checking multiple typeclass instances of multiple types. Consider the following Haskell source file:

    import Data.Proxy (Proxy(..))
    import Data.Map (Map)
    import Data.Set (Set)

    -- A Proxy for Set Int.
    setInt :: Proxy (Set Int)
    setInt = Proxy

    -- A Proxy for Map Int Int.
    mapInt :: Proxy (Map Int Int)
    mapInt = Proxy

    myLaws :: Proxy a -> [Laws]
    myLaws p = [eqLaws p, monoidLaws p]

    namedTests :: [(String, [Laws])]
    namedTests =
      [ ("Set Int", myLaws setInt)
      , ("Map Int Int", myLaws mapInt)
      ]

Now, in GHCi:

    >>> lawsCheckMany namedTests

    Testing properties for common typeclasses
    -------------
    -- Set Int --
    -------------

    Eq: Transitive +++ OK, passed 100 tests.
    Eq: Symmetric +++ OK, passed 100 tests.
    Eq: Reflexive +++ OK, passed 100 tests.
    Monoid: Associative +++ OK, passed 100 tests.
    Monoid: Left Identity +++ OK, passed 100 tests.
    Monoid: Right Identity +++ OK, passed 100 tests.
    Monoid: Concatenation +++ OK, passed 100 tests.

    -----------------
    -- Map Int Int --
    -----------------

    Eq: Transitive +++ OK, passed 100 tests.
    Eq: Symmetric +++ OK, passed 100 tests.
    Eq: Reflexive +++ OK, passed 100 tests.
    Monoid: Associative +++ OK, passed 100 tests.
    Monoid: Left Identity +++ OK, passed 100 tests.
    Monoid: Right Identity +++ OK, passed 100 tests.
    Monoid: Concatenation +++ OK, passed 100 tests.

In the case of a failing test, the program terminates with exit code 1.

lawsCheckOne :: Proxy a -> [Proxy a -> Laws] -> IO () Source #

A convenience function that allows one to check many typeclass instances of the same type.

    >>> specialisedLawsCheckMany (Proxy :: Proxy Word) [jsonLaws, showReadLaws]
    ToJSON/FromJSON: Encoding Equals Value +++ OK, passed 100 tests.
    ToJSON/FromJSON: Partial Isomorphism +++ OK, passed 100 tests.
    Show/Read: Partial Isomorphism +++ OK, passed 100 tests.

# Properties

## Ground types

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

Tests the following properties:

Conjunction Idempotence
  `n .&. n ≡ n`
Disjunction Idempotence
  `n .|. n ≡ n`
Double Complement
  `complement (complement n) ≡ n`
Set Bit
  `setBit n i ≡ n .|. bit i`
Clear Bit
  `clearBit n i ≡ n .&. complement (bit i)`
Complement Bit
  `complementBit n i ≡ xor n (bit i)`
Clear Zero
  `clearBit zeroBits i ≡ zeroBits`
Set Zero
  `setBit zeroBits i ≡ bit i`
Test Zero
  `testBit zeroBits i ≡ False`
Pop Zero
  `popCount zeroBits ≡ 0`
Right Rotation
  `no sign extension → (rotateR n i ≡ (shiftR n i) .|. (shiftL n (finiteBitSize ⊥ - i)))`
Left Rotation
  `no sign extension → (rotateL n i ≡ (shiftL n i) .|. (shiftR n (finiteBitSize ⊥ - i)))`
Count Leading Zeros of Zero
  `countLeadingZeros zeroBits ≡ finiteBitSize ⊥`
Count Trailing Zeros of Zero
  `countTrailingZeros zeroBits ≡ finiteBitSize ⊥`

All of the useful instances of the `Bits` typeclass also have `FiniteBits` instances, so these property tests actually require that instance as well.

Note: This property test is only available when using `base-4.7` or newer.

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

Tests the following properties:

Transitive
  `a `==` b ∧ b `==` c ⇒ a `==` c`
Symmetric
  `a `==` b ⇒ b `==` a`
Reflexive
  `a `==` a`
Negation
  `x `/=` y `==` `not` (x `==` y)`

Some of these properties involve implication. In the case that the left hand side of the implication arrow does not hold, we do not retry. Consequently, these properties only end up being useful when the data type has a small number of inhabitants.

substitutiveEqLaws :: (Eq a, Arbitrary a, CoArbitrary a, Function a, Show a) => Proxy a -> Laws Source #

Tests the following properties:

Substitutive
  `x `==` y ⇒ f x `==` f y`

Note: This does not test `eqLaws`. If you want to use this, You should use it in addition to `eqLaws`.

numLaws :: (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Laws Source #

Tests the following properties:

Additive Commutativity
  `a + b ≡ b + a`
Additive Left Identity
  `0 + a ≡ a`
Additive Right Identity
  `a + 0 ≡ a`
Multiplicative Associativity
  `a * (b * c) ≡ (a * b) * c`
Multiplicative Left Identity
  `1 * a ≡ a`
Multiplicative Right Identity
  `a * 1 ≡ a`
Multiplication Left Distributes Over Addition
  `a * (b + c) ≡ (a * b) + (a * c)`
Multiplication Right Distributes Over Addition
  `(a + b) * c ≡ (a * c) + (b * c)`
Multiplicative Left Annihilation
  `0 * a ≡ 0`
Multiplicative Right Annihilation
  `a * 0 ≡ 0`
Additive Inverse
  ``negate` a `+` a ≡ 0`
Subtraction
  `a `+` `negate` b ≡ a `-` b`
Abs Is Idempotent
  @`abs` (`abs` a) ≡ `abs` a
Signum Is Idempotent
  @`signum` (`signum` a) ≡ `signum` a
Product Of Abs And Signum Is Id
  ``abs` a * `signum` a ≡ a`

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

Tests the following properties:

Quotient Remainder
  `(quot x y) * y + (rem x y) ≡ x`
Division Modulus
  `(div x y) * y + (mod x y) ≡ x`
Integer Roundtrip
  `fromInteger (toInteger x) ≡ x`
QuotRem is (Quot, Rem)
  `quotRem x y ≡ (quot x y, rem x y)`
DivMod is (Div, Mod)
  `divMod x y ≡ (div x y, mod x y)`

ixLaws :: (Ix a, Arbitrary a, Show a) => Proxy a -> Laws Source #

Tests the various `Ix` properties:

    inRange (l,u) i == elem i (range (l,u))

``range` (l,u) `!!` `index` (l,u) i `==` i`, when ``inRange` (l,u) i`

    map (index (l,u)) (range (l,u)) == [0 .. rangeSize (l,u) - 1]

    rangeSize (l,u) == length (range (l,u))

isListLaws :: (IsList a, Show a, Show (Item a), Arbitrary a, Arbitrary (Item a), Eq a) => Proxy a -> Laws Source #

Tests the following properties:

Partial Isomorphism
  `fromList . toList ≡ id`
Length Preservation
  `fromList xs ≡ fromListN (length xs) xs`

Note: This property test is only available when using `base-4.7` or newer.

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

Tests the following properties:

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

Note that in the second property, the type of decode is `ByteString -> Value`, not `ByteString -> a`

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

Tests the following properties:

Associative
  `mappend a (mappend b c) ≡ mappend (mappend a b) c`
Left Identity
  `mappend mempty a ≡ a`
Right Identity
  `mappend a mempty ≡ a`
Concatenation
  `mconcat as ≡ foldr mappend mempty as`

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

Tests the following properties:

Commutative
  `mappend a b ≡ mappend b a`

Note that this does not test associativity or identity. Make sure to use `monoidLaws` in addition to this set of laws.

semigroupMonoidLaws :: (Semigroup a, Monoid a, Eq a, Arbitrary a, Show a) => Proxy a -> Laws Source #

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

Tests the following properties:

Antisymmetry
  `a ≤ b ∧ b ≤ a ⇒ a = b`
Transitivity
  `a ≤ b ∧ b ≤ c ⇒ a ≤ c`
Totality
  `a ≤ b ∨ a > b`

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

Tests the following properties:

Succ Pred Identity
  ``succ` (`pred` x) ≡ x`
Pred Succ Identity
  ``pred` (`succ` x) ≡ x`

This only works for `Enum` types that are not bounded, meaning that `succ` and `pred` must be total. This means that these property tests work correctly for types like `Integer` but not for `Int`.

Sadly, there is not a good way to test `fromEnum` and `toEnum`, since many types that have reasonable implementations for `succ` and `pred` have more inhabitants than `Int` does.

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

Tests the same properties as `enumLaws` except that it requires the type to have a `Bounded` instance. These tests avoid taking the successor of the maximum element or the predecessor of the minimal element.

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

Test that a `Prim` instance obey the several laws.

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

Tests the following properties:

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

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

Tests the following properties:

Commutative
  `a `<>` b ≡ b `<>` a`

Note that this does not test associativity. Make sure to use `semigroupLaws` in addition to this set of laws.

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

Tests the following properties:

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

Note that this does not test associativity. Make sure to use `semigroupLaws` in addition to this set of laws.

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

Tests the following properties:

Idempotent
  `a `<>` a ≡ a`

Note that this does not test associativity. Make sure to use `semigroupLaws` in addition to this set of laws. In literature, this class of semigroup is known as a band.

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

Tests the following properties:

Rectangular Band
  `a `<>` b `<>` a ≡ a`

Note that this does not test associativity. Make sure to use `semigroupLaws` in addition to this set of laws.

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

Tests the following properties:

Additive Commutativity
  `a + b ≡ b + a`
Additive Left Identity
  `0 + a ≡ a`
Additive Right Identity
  `a + 0 ≡ a`
Multiplicative Associativity
  `a * (b * c) ≡ (a * b) * c`
Multiplicative Left Identity
  `1 * a ≡ a`
Multiplicative Right Identity
  `a * 1 ≡ a`
Multiplication Left Distributes Over Addition
  `a * (b + c) ≡ (a * b) + (a * c)`
Multiplication Right Distributes Over Addition
  `(a + b) * c ≡ (a * c) + (b * c)`
Multiplicative Left Annihilation
  `0 * a ≡ 0`
Multiplicative Right Annihilation
  `a * 0 ≡ 0`

Also tests that `fromNatural` is a homomorphism of semirings:

FromNatural Maps Zero
  `fromNatural` 0 = `zero`
FromNatural Maps One
  `fromNatural` 1 = `one`
FromNatural Maps Plus
  `fromNatural` (`a` + `b`) = `fromNatural` `a` + `fromNatural` `b`
FromNatural Maps Times
  `fromNatural` (`a` * `b`) = `fromNatural` `a` * `fromNatural` `b`

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

Tests the following properties:

Additive Inverse
  ``negate` a `+` a ≡ 0`

Note that this does not test any of the laws tested by `semiringLaws`.

gcdDomainLaws :: (Eq a, GcdDomain a, Arbitrary a, Show a) => Proxy a -> Laws Source #

Test that a `GcdDomain` instance obey several laws.

Check that `divide` is an inverse of times:

- `y /= 0 => (x * y) `divide` y == Just x`,
- `y /= 0, x `divide` y == Just z => x == z * y`.

Check that `gcd` is a common divisor and is a multiple of any common divisor:

- `x /= 0, y /= 0 => isJust (x `divide` gcd x y) && isJust (y `divide` gcd x y)`,
- `z /= 0 => isJust (gcd (x * z) (y * z) `divide` z)`.

Check that `lcm` is a common multiple and is a factor of any common multiple:

- `x /= 0, y /= 0 => isJust (lcm x y `divide` x) && isJust (lcm x y `divide` y)`,
- `x /= 0, y /= 0, isJust (z `divide` x), isJust (z `divide` y) => isJust (z `divide` lcm x y)`.

Check that `gcd` of `coprime` numbers is a unit of the semiring (has an inverse):

- `y /= 0, coprime x y => isJust (1 `divide` gcd x y)`.

euclideanLaws :: (Eq a, Euclidean a, Arbitrary a, Show a) => Proxy a -> Laws Source #

Test that a `Euclidean` instance obey laws of a Euclidean domain.

- `y /= 0, r == x `rem` y => r == 0 || degree r < degree y`,
- `y /= 0, (q, r) == x `quotRem` y => x == q * y + r`,
- `y /= 0 => x `quot` x y == fst (x `quotRem` y)`,
- `y /= 0 => x `rem` x y == snd (x `quotRem` y)`.

showLaws :: (Show a, Arbitrary a) => Proxy a -> Laws Source #

Tests the following properties:

Show
  ``show` a ≡ `showsPrec` 0 a ""`
Equivariance: `showsPrec`
  ``showsPrec` p a r `++` s ≡ `showsPrec` p a (r `++` s)`
Equivariance: `showList`
  ``showList` as r `++` s ≡ `showList` as (r `++` s)`

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

Tests the following properties:

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

Note: When using `base-4.5` or older, a shim implementation of `readMaybe` is used.

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

Tests the following `Storable` properties:

Set-Get
  `(`pokeElemOff` ptr ix a >> `peekElemOff` ptr ix') ≡ `pure` a`
Get-Set
  `(`peekElemOff` ptr ix >> `pokeElemOff` ptr ix a) ≡ `pure` a`

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

Tests the following properties:

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

Note: This property test is only available when using `base-4.5` or newer.

Note: `from` and `to` don't actually care about the type variable `x` in ``Rep` a x`, so here we instantiate it to ``()`` by default. If you would like to instantiate `x` as something else, please file a bug report.

generic1Laws :: forall (f :: Type -> Type) proxy. (Generic1 f, Eq1 f, Arbitrary1 f, Show1 f, Eq1 (Rep1 f), Show1 (Rep1 f), Arbitrary1 (Rep1 f)) => proxy f -> Laws Source #

Tests the following properties:

From-To Inverse
  ``from1` `.` `to1` ≡ `id``
To-From Inverse
  ``to1` `.` `from1` ≡ `id``

Note: This property test is only available when using `base-4.9` or newer.

## Unary type constructors

alternativeLaws :: forall (f :: Type -> Type) proxy. (Alternative f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => proxy f -> Laws Source #

Tests the following alternative properties:

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

altLaws :: forall proxy (f :: Type -> Type). (Alt f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => proxy f -> Laws Source #

Tests the following alt properties:

Associativity
  `(a `<!>` b) `<!>` c ≡ a `<!>` (b `<!>` c)`
Left Distributivity
  `f `<$>` (a `<!>` b) ≡ (f `<$>` a) `<!>` (f `<$>` b)`

applyLaws :: forall (f :: Type -> Type) proxy. (Apply f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => proxy f -> Laws Source #

Tests the following alt properties:

LiftF2 (1)
  `(`<.>`) ≡ `liftF2` `id``
Associativity
  ``fmap` (`.`) u `<.>` v `<.>` w ≡ u `<.>` (v `<.>` w)`

applicativeLaws :: forall (f :: Type -> Type) proxy. (Applicative f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => proxy f -> Laws Source #

Tests the following applicative properties:

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

contravariantLaws :: forall (f :: Type -> Type) proxy. (Contravariant f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => proxy f -> Laws Source #

Tests the following contravariant properties:

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

foldableLaws :: forall proxy (f :: Type -> Type). (Foldable f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => proxy f -> Laws Source #

Tests the following `Foldable` properties:

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 xs ≡ let f' k x z = k `$!` f x z in `foldl` f' `id` xs z0`
foldr1
  ``foldr1` f t ≡ let `Just` (xs,x) = `unsnoc` (`toList` t) in `foldr` f x xs`
foldl
  ``foldl` f z t ≡ `appEndo` (`getDual` (`foldMap` (`Dual` . `Endo` . `flip` f) t)) z`
foldl'
  ``foldl'` f z0 xs ≡ let f' x k z = k `$!` f z x in `foldr` f' `id` xs z0`
foldl1
  ``foldl1` f t ≡ let x : xs = `toList` t in `foldl` f x xs`
toList
  ``toList` ≡ `foldr` (:) []`
null
  ``null` ≡ `foldr` (`const` (`const` `False`)) `True``
length
  ``length` ≡ `getSum` . `foldMap` (`const` (`Sum` 1))`

Note that this checks to ensure that `foldl'` and `foldr'` are suitably strict.

functorLaws :: forall (f :: Type -> Type) proxy. (Functor f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => proxy f -> Laws Source #

Tests the following functor properties:

Identity
  ``fmap` `id` ≡ `id``
Composition
  ``fmap` (f `.` g) ≡ `fmap` f `.` `fmap` g`
Const
  `(`<$`) ≡ `fmap` `const``

monadLaws :: forall (f :: Type -> Type) proxy. (Monad f, Applicative f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => proxy f -> Laws Source #

Tests the following monadic properties:

Left Identity
  ``return` a `>>=` k ≡ k a`
Right Identity
  `m `>>=` `return` ≡ m`
Associativity
  `m `>>=` (\x -> k x `>>=` h) ≡ (m `>>=` k) `>>=` h`
Return
  ``pure` ≡ `return``
Ap
  `(`<*>`) ≡ `ap``

monadPlusLaws :: forall (f :: Type -> Type) proxy. (MonadPlus f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => proxy f -> Laws Source #

Tests the following monad plus properties:

Left Identity
  ``mplus` `mzero` x ≡ x`
Right Identity
  ``mplus` x `mzero` ≡ x`
Associativity
  ``mplus` a (`mplus` b c) ≡ `mplus` (`mplus` a b) c)`
Left Zero
  ``mzero` `>>=` f ≡ `mzero``
Right Zero
  `m `>>` `mzero` ≡ `mzero``

monadZipLaws :: forall (f :: Type -> Type) proxy. (MonadZip f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => proxy f -> Laws Source #

Tests the following monadic zipping properties:

Naturality
  ``liftM` (f `***` g) (`mzip` ma mb) = `mzip` (`liftM` f ma) (`liftM` g mb)`

In the laws above, the infix function ``***`` refers to a typeclass method of `Arrow`.

plusLaws :: forall proxy (f :: Type -> Type). (Plus f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => proxy f -> Laws Source #

Tests the following alt properties:

Left Identity
  ``zero` `<!>` m ≡ m`
Right Identity
  `m `<!>` `zero` ≡ m`

extendedPlusLaws :: forall proxy (f :: Type -> Type). (Plus f, Alternative f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => proxy f -> Laws Source #

Tests everything from `altLaws`, plus the following:

Congruency
  ``zero` ≡ `empty``

traversableLaws :: forall (f :: Type -> Type) proxy. (Traversable f, forall a. Eq a => Eq (f a), forall a. Show a => Show (f a), forall a. Arbitrary a => Arbitrary (f a)) => proxy f -> Laws Source #

Tests the following `Traversable` properties:

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`
Sequence Naturality
  `t `.` `sequenceA` ≡ `sequenceA` `.` `fmap` t` for every applicative transformation `t`
Sequence Identity
  ``sequenceA` `.` `fmap` `Identity` ≡ `Identity``
Sequence Composition
  ``sequenceA` `.` `fmap` `Compose` ≡ `Compose` `.` `fmap` `sequenceA` `.` `sequenceA``
foldMap
  ``foldMap` ≡ `foldMapDefault``
fmap
  ``fmap` ≡ `fmapDefault``

Where an applicative transformation is a function

    t :: (Applicative f, Applicative g) => f a -> g a

preserving the `Applicative` operations, i.e.

- Identity: `t (`pure` x) ≡ `pure` x`
- Distributivity: `t (x `<*>` y) ≡ t x `<*>` t y`

## Binary type constructors

bifoldableLaws :: forall proxy (f :: Type -> Type -> Type). (Bifoldable f, forall a b. (Eq a, Eq b) => Eq (f a b), forall a b. (Show a, Show b) => Show (f a b), forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (f a b)) => proxy f -> Laws Source #

Tests the following `Bifunctor` properties:

Bifold Identity
  ``bifold` ≡ `bifoldMap` `id` `id``
BifoldMap Identity
  ``bifoldMap` f g ≡ `bifoldr` (`mappend` `.` f) (`mappend` `.` g) `mempty``
Bifoldr Identity
  ``bifoldr` f g z t ≡ `appEndo` (`bifoldMap` (`Endo` `.` f) (`Endo` `.` g) t) z`

Note: This property test is only available when this package is built with `base-4.10+` or `transformers-0.5+`.

bifunctorLaws :: forall proxy (f :: Type -> Type -> Type). (Bifunctor f, forall a b. (Eq a, Eq b) => Eq (f a b), forall a b. (Show a, Show b) => Show (f a b), forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (f a b)) => proxy f -> Laws Source #

Tests the following `Bifunctor` properties:

Identity
  ``bimap` `id` `id` ≡ `id``
First Identity
  ``first` `id` ≡ `id``
Second Identity
  ``second` `id` ≡ `id``
Bifunctor Composition
  ``bimap` f g ≡ `first` f `.` `second` g`

Note: This property test is only available when this package is built with `base-4.9+` or `transformers-0.5+`.

bitraversableLaws :: forall proxy (f :: Type -> Type -> Type). (Bitraversable f, forall a b. (Eq a, Eq b) => Eq (f a b), forall a b. (Show a, Show b) => Show (f a b), forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (f a b)) => proxy f -> Laws Source #

Tests the following `Bitraversable` properties:

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 g2 `.` f1) (`Compose` `.` `fmap` g2 `.` f2)`

Note: This property test is only available when this package is built with `base-4.9+` or `transformers-0.5+`.

categoryLaws :: forall proxy (c :: Type -> Type -> Type). (Category c, forall a b. (Eq a, Eq b) => Eq (c a b), forall a b. (Show a, Show b) => Show (c a b), forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (c a b)) => proxy c -> Laws Source #

Tests the following `Category` properties:

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

Note: This property test is only available when this package is built with `base-4.9+` or `transformers-0.5+`.

commutativeCategoryLaws :: forall proxy (c :: Type -> Type -> Type). (Category c, forall a b. (Eq a, Eq b) => Eq (c a b), forall a b. (Show a, Show b) => Show (c a b), forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (c a b)) => proxy c -> Laws Source #

Test everything from `categoryLaws` plus the following:

Commutative
  `f `.` g ≡ g `.` f`

Note: This property test is only available when this package is built with `base-4.9+` or `transformers-0.5+`.

semigroupoidLaws :: forall proxy (s :: Type -> Type -> Type). (Semigroupoid s, forall a b. (Eq a, Eq b) => Eq (s a b), forall a b. (Show a, Show b) => Show (s a b), forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (s a b)) => proxy s -> Laws Source #

Tests the following `Semigroupoid` properties:

Associativity
  `f ``o'` (g ``o'` h) ≡ (f ``o'` g) ``o'` h`

Note: This property test is only available when this package is built with `base-4.9+` or `transformers-0.5+`.

commutativeSemigroupoidLaws :: forall proxy (s :: Type -> Type -> Type). (Semigroupoid s, forall a b. (Eq a, Eq b) => Eq (s a b), forall a b. (Show a, Show b) => Show (s a b), forall a b. (Arbitrary a, Arbitrary b) => Arbitrary (s a b)) => proxy s -> Laws Source #

Tests everything from `semigroupoidLaws` plus the following:

Commutative
  `f ``o'` g ≡ g ``o'` f`

Note: This property test is only available when this package is built with `base-4.9+` or `transformers-0.5+`.

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

Test that a `MVector` instance obey several laws.

# Types

data Laws Source #

A set of laws associated with a typeclass.

Note: Most of the top-level functions provided by this library have the shape `forall a. (Ctx a) => Proxy a -> Laws`. You can just as easily provide your own `Laws` in libraries/test suites using regular QuickCheck machinery.

Constructors

Laws |

Fields

- lawsTypeclass :: String

  Name of the typeclass whose laws are tested

- lawsProperties :: [(String, Property)]

  Pairs of law name and property

data Proxy1 (f :: Type -> Type) Source #

In older versions of GHC, Proxy is not poly-kinded, so we provide Proxy1.

Constructors

Proxy1 |

data Proxy2 (f :: Type -> Type -> Type) Source #

In older versions of GHC, Proxy is not poly-kinded, so we provide Proxy2.

Constructors

Proxy2 |