leancheck-1.0.0: Enumerative property-based testing
Copyright(c) 2015-2020 Rudy Matela
License3-Clause BSD (see the file LICENSE)
MaintainerRudy Matela <rudy@matela.com.br>
Safe HaskellNone
LanguageHaskell2010

Test.LeanCheck.Utils.Operators

Description

This module is part of LeanCheck, a simple enumerative property-based testing library.

Some operators for property-based testing.

Synopsis

Combining properties

(==>) :: Bool -> Bool -> Bool infixr 0 Source #

Boolean implication operator. Useful for defining conditional properties:

prop_something x y  =  condition x y ==> something x y

Examples:

> prop_addMonotonic x y  =  y > 0 ==> x + y > x
> check prop_addMonotonic
+++ OK, passed 200 tests.

(===) :: Eq b => (a -> b) -> (a -> b) -> a -> Bool infix 4 Source #

Allows building equality properties between functions.

prop_id_idempotent  =  id === id . id
> check $ id === (+0)
+++ OK, passed 200 tests.
> check $ id === id . id
+++ OK, passed 1 tests (exhausted).
> check $ id === (+1)
*** Failed! Falsifiable (after 1 tests):
0

(====) :: Eq c => (a -> b -> c) -> (a -> b -> c) -> a -> b -> Bool infix 4 Source #

Allows building equality properties between two-argument functions.

> holds 100 $ const ==== asTypeOf
True
> holds 100 $ (+) ==== flip (+)
True
> holds 100 $ (+) ==== (*)
False

(&&&) :: (a -> Bool) -> (a -> Bool) -> a -> Bool infixr 3 Source #

And (&&) operator over one-argument properties.

Allows building conjuntions between one-argument properties:

> holds 100 $ id === (+0) &&& id === (id . id)
True

(&&&&) :: (a -> b -> Bool) -> (a -> b -> Bool) -> a -> b -> Bool infixr 3 Source #

And (&&) operator over two-argument properties.

Allows building conjuntions between two-argument properties:

> holds 100 $ (+) ==== flip (+) &&&& (+) ==== (*)
False

(&&&&&) :: (a -> b -> c -> Bool) -> (a -> b -> c -> Bool) -> a -> b -> c -> Bool infixr 3 Source #

And operator over three-argument properties.

(|||) :: (a -> Bool) -> (a -> Bool) -> a -> Bool infixr 2 Source #

Or (||) operator over one-argument properties.

Allows building disjunctions between one-argument properties:

> holds 100 $ id === (+0) ||| id === (id . id)
True

(||||) :: (a -> b -> Bool) -> (a -> b -> Bool) -> a -> b -> Bool infixr 2 Source #

Or (||) operator over two-argument properties.

Allows building conjuntions between two-argument properties:

> holds 100 $ (+) ==== flip (+) |||| (+) ==== (*)
True

Properties of unary functions

isIdempotent :: Eq a => (a -> a) -> a -> Bool Source #

Is the given function idempotent? f (f x) == x

> check $ isIdempotent abs
+++ OK, passed 200 tests.
> check $ isIdempotent sort
+++ OK, passed 200 tests.
> check $ isIdempotent negate
*** Failed! Falsifiable (after 2 tests):
1

isIdentity :: Eq a => (a -> a) -> a -> Bool Source #

Is the given function an identity? f x == x

> check $ isIdentity (+0)
+++ OK, passed 200 tests.
> check $ isIdentity (sort :: [()]->[()])
+++ OK, passed 200 tests.
> check $ isIdentity (not . not)
+++ OK, passed 2 tests (exhausted).

isNeverIdentity :: Eq a => (a -> a) -> a -> Bool Source #

Is the given function never an identity? f x /= x

> check $ neverIdentity not
+++ OK, passed 2 tests (exhausted).
> check $ neverIdentity negate
*** Failed! Falsifiable (after 1 tests):
0

Note: this is not the same as not being an identity.

Properties of operators (binary functions)

isCommutative :: Eq b => (a -> a -> b) -> a -> a -> Bool Source #

Is a given operator commutative? x + y = y + x

> check $ isCommutative (+)
+++ OK, passed 200 tests.
> import Data.List
> check $ isCommutative (union :: [Int]->[Int]->[Int])
*** Failed! Falsifiable (after 4 tests):
[] [0,0]

isAssociative :: Eq a => (a -> a -> a) -> a -> a -> a -> Bool Source #

Is a given operator associative? x + (y + z) = (x + y) + z

> check $ isAssociative (+)
+++ OK, passed 200 tests.
> check $ isAssociative (-)
*** Failed! Falsifiable (after 2 tests):
0 0 1

isDistributiveOver :: Eq a => (a -> a -> a) -> (a -> a -> a) -> a -> a -> a -> Bool Source #

Does the first operator, left-distributes over the second?

This is an alias to isLeftDistributiveOver.

isLeftDistributiveOver :: Eq a => (a -> a -> a) -> (a -> a -> a) -> a -> a -> a -> Bool Source #

Does the first operator, left-distributes over the second? x * (y + z) = (x * y) + (x * z)

> check $ (*) `isLeftDistributiveOver` (+)
+++ OK, passed 200 tests.
> check $ (+) `isLeftDistributiveOver` (*)
*** Failed! Falsifiable (after 8 tests):
1 0 1

isRightDistributiveOver :: Eq a => (a -> a -> a) -> (a -> a -> a) -> a -> a -> a -> Bool Source #

Does the first operator, right-distributes over the second? (y + z) * x = (y * x) + (z * x)

> check $ (*) `isRightDistributiveOver` (+)
+++ OK, passed 200 tests.
> check $ (+) `isRightDistributiveOver` (*)
*** Failed! Falsifiable (after 8 tests):
1 0 1

isFlipped :: Eq c => (a -> b -> c) -> (b -> a -> c) -> a -> b -> Bool Source #

Are two operators flipped versions of each other?

> check $ ((<) `isFlipped` (>) :: Int -> Int -> Bool)
+++ OK, passed 200 tests.
> check $ ((<=) `isFlipped` (>=) :: Int -> Int -> Bool)
+++ OK, passed 200 tests.
> check $ ((<) `isFlipped` (>=) :: Int -> Int -> Bool)
*** Failed! Falsifiable (after 1 tests):
0 0
> check $ ((<=) `isFlipped` (>) :: Int -> Int -> Bool)
*** Failed! Falsifiable (after 1 tests):
0 0

Properties of relations (binary functions returning truth values)

isTransitive :: (a -> a -> Bool) -> a -> a -> a -> Bool Source #

Is a given relation transitive?

A relation is transitive when if a is related to b then b is related to c.

> check $ isTransitive ((==) :: Int->Int->Bool)
+++ OK, passed 200 tests.
> check $ isTransitive ((/=) :: Int->Int->Bool)
*** Failed! Falsifiable (after 3 tests):
0 1 0

isReflexive :: (a -> a -> Bool) -> a -> Bool Source #

Is a given relation reflexive?

A relation is reflexive when an element is always related to itself.

> check $ isReflexive ((==) :: Int->Int->Bool)
+++ OK, passed 200 tests.
> check $ isReflexive ((/=) :: Int->Int->Bool)
*** Failed! Falsifiable (after 1 tests):
0

isIrreflexive :: (a -> a -> Bool) -> a -> Bool Source #

Is a given relation irreflexive?

A given relation is irreflexive or anti-reflexive when an element is _never_ related to itself.

This is not the negation of isReflexive.

> check $ isIrreflexive ((==) :: Int->Int->Bool)
*** Failed! Falsifiable (after 1 tests):
0
> check $ isIrreflexive ((/=) :: Int->Int->Bool)
+++ OK, passed 200 tests.

isSymmetric :: (a -> a -> Bool) -> a -> a -> Bool Source #

Is a given relation symmetric?

A relation is symmetric when if a is related to b, then b is related to a.

> check $ isSymmetric (&&)
+++ OK, passed 4 tests (exhausted).
> check $ isSymmetric (==>)
*** Failed! Falsifiable (after 2 tests):
False True

This is a type-restricted version of isCommutative.

isAsymmetric :: (a -> a -> Bool) -> a -> a -> Bool Source #

Is a given relation asymmetric?

Not to be confused with not isSymmetric and isAntisymmetric.

> check $ isAsymmetric ((<=) :: Int->Int->Bool)
*** Failed! Falsifiable (after 1 tests):
0 0
> check $ isAsymmetric ((<) :: Int->Int->Bool)
+++ OK, passed 200 tests.

isAntisymmetric :: Eq a => (a -> a -> Bool) -> a -> a -> Bool Source #

Is a given relation antisymmetric?

Not to be confused with isAsymmetric. Not to be confused with the negation of isSymmetric.

> check $ isAntisymmetric ((<=) :: Int->Int->Bool)
+++ OK, passed 200 tests.
> check $ isAntisymmetric ((/=) :: Int->Int->Bool)
*** Failed! Falsifiable (after 2 tests):
0 1

Properties of order relations

isEquivalence :: (a -> a -> Bool) -> a -> a -> a -> Bool Source #

Is the given binary relation an equivalence?

In other words, is the given relation reflexive, symmetric and transitive?

> check (isEquivalence (==) :: Int -> Int -> Int -> Bool)
+++ OK, passed 200 tests.
> check (isEquivalence (<=) :: Int -> Int -> Int -> Bool)
*** Failed! Falsifiable (after 3 tests):
0 1 0

Or, using Test.LeanCheck.Utils.TypeBinding:

> check $ isEquivalence (<=) -:> int
*** Failed! Falsifiable (after 3 tests):
0 1 0

isPartialOrder :: Eq a => (a -> a -> Bool) -> a -> a -> a -> Bool Source #

Is the given binary relation a partial order?

In other words, is the given relation reflexive, antisymmetric and transitive?

> check $ isPartialOrder ((<) :: Int->Int->Bool)
*** Failed! Falsifiable (after 1 tests):
0 0 0
> check $ isPartialOrder ((<=) :: Int->Int->Bool)
+++ OK, passed 200 tests.
> check $ isPartialOrder isSubsetOf
+++ OK, passed 200 tests.

isStrictPartialOrder :: (a -> a -> Bool) -> a -> a -> a -> Bool Source #

Is the given binary relation a strict partial order?

In other words, is the given relation irreflexive, asymmetric and transitive?

> check $ isStrictPartialOrder ((<) :: Int->Int->Bool)
+++ OK, passed 200 tests.
> check $ isStrictPartialOrder ((<=) :: Int->Int->Bool)
*** Failed! Falsifiable (after 1 tests):
0 0 0

isTotalOrder :: Eq a => (a -> a -> Bool) -> a -> a -> a -> Bool Source #

Is the given binary relation a total order?

> check $ isTotalOrder ((<) :: Int->Int->Bool)
*** Failed! Falsifiable (after 1 tests):
0 0 0
> check $ isTotalOrder ((<=) :: Int->Int->Bool)
+++ OK, passed 200 tests.

isStrictTotalOrder :: Eq a => (a -> a -> Bool) -> a -> a -> a -> Bool Source #

Is the given binary relation a strict total order?

> check $ isStrictTotalOrder ((<=) :: Int->Int->Bool)
*** Failed! Falsifiable (after 1 tests):
0 0 0
> check $ isStrictTotalOrder ((<) :: Int->Int->Bool)
+++ OK, passed 200 tests.

isComparison :: (a -> a -> Ordering) -> a -> a -> a -> Bool Source #

Does the given compare function follow the required properties?

This is useful for testing custom Ord instances.

> check $ isComparison (compare :: Int->Int->Ordering)
+++ OK, passed 200 tests.

Ternary comparison operators

(=$) :: Eq b => a -> (a -> b) -> a -> Bool infixl 4 Source #

Equal under, a ternary operator with the same fixity as ==.

x =$ f $= y  =  f x == f y
> [1,2,3,4,5] =$ take 2 $= [1,2,4,8,16]
True
> [1,2,3,4,5] =$ take 3 $= [1,2,4,8,16]
False
> [1,2,3] =$ sort $= [3,2,1]
True
> 42 =$ (`mod` 10) $= 16842
True
> 42 =$ (`mod`  9) $= 16842
False
> 'a' =$ isLetter $= 'b'
True
> 'a' =$ isLetter $= '1'
False

($=) :: (a -> Bool) -> a -> Bool infixl 4 Source #

See =$

(=|) :: Eq a => [a] -> Int -> [a] -> Bool infixl 4 Source #

Check if two lists are equal for n values. This operator has the same fixity of ==.

xs =| n |= ys  =  take n xs == take n ys
[1,2,3,4,5] =| 2 |= [1,2,4,8,16] -- > True
[1,2,3,4,5] =| 3 |= [1,2,4,8,16] -- > False

(|=) :: (a -> Bool) -> a -> Bool infixl 4 Source #

See =|

Properties for typeclass instances

okEq :: Eq a => a -> a -> a -> Bool Source #

Is this Eq instance valid?

This is useful for testing your custom Eq instances against required properties.

In particular, this function tests that == is an equivalence and that /= is the negation of ==.

> check $ (okEq :: Int -> Int -> Int -> Bool)
+++ OK, passed 200 tests.
> check $ (okEq :: Bool -> Bool -> Bool -> Bool)
+++ OK, passed 8 tests (exhausted).

okOrd :: Ord a => a -> a -> a -> Bool Source #

Is this Ord instance valid?

This is useful for testing your custom Ord instances against required properties.

> check $ (okOrd :: Int -> Int -> Int -> Bool)
+++ OK, passed 200 tests.
> check $ (okOrd :: Bool -> Bool -> Bool -> Bool)
+++ OK, passed 8 tests (exhausted).

okEqOrd :: (Eq a, Ord a) => a -> a -> a -> Bool Source #

Is this Eq and Ord instance valid and consistent?

This is useful for testing your custom Eq and Ord instances against required properties.

> check $ (okEqOrd :: Int -> Int -> Int -> Bool)
+++ OK, passed 200 tests.
> check $ (okEqOrd :: Bool -> Bool -> Bool -> Bool)
+++ OK, passed 8 tests (exhausted).

okNum :: (Eq a, Num a) => a -> a -> a -> Bool Source #

Is this Num instance valid?

This is useful for testing your custom Num instances against required properties.

> check (okNum :: Int -> Int -> Int -> Bool)
+++ OK, passed 200 tests.

Double is mostly valid, but not entirely valid:

> check (okNum :: Double -> Double -> Double -> Bool)
*** Failed! Falsifiable (after 6 tests):
  1. 0 0.0 Infinity

okNumNonNegative :: (Eq a, Num a) => a -> a -> a -> Bool Source #

Like okNum but restricted to zero and positives.

> check (okNumNonNegative :: Natural -> Natural -> Natural -> Bool)
+++ OK, passed 200 tests.

Deprecated functions

idempotent :: Eq a => (a -> a) -> a -> Bool Source #

Deprecated: Use isIdempotent.

Deprecated: use isIdempotent.

identity :: Eq a => (a -> a) -> a -> Bool Source #

Deprecated: Use isIdentity.

Deprecated: use isIdentity.

neverIdentity :: Eq a => (a -> a) -> a -> Bool Source #

Deprecated: Use isNeverIdentity.

Deprecated: use isNeverIdentity.

commutative :: Eq b => (a -> a -> b) -> a -> a -> Bool Source #

Deprecated: Use isCommutative.

Deprecated: use isCommutative.

associative :: Eq a => (a -> a -> a) -> a -> a -> a -> Bool Source #

Deprecated: Use isAssociative.

Deprecated: use isAssociative.

distributive :: Eq a => (a -> a -> a) -> (a -> a -> a) -> a -> a -> a -> Bool Source #

Deprecated: Use isDistributiveOver.

Deprecated: use isDistributiveOver.

symmetric2 :: Eq c => (a -> b -> c) -> (b -> a -> c) -> a -> b -> Bool Source #

Deprecated: Use isFlipped.

Deprecated: use isFlipped.

transitive :: (a -> a -> Bool) -> a -> a -> a -> Bool Source #

Deprecated: Use isTransitive.

Deprecated: use isTransitive.

reflexive :: (a -> a -> Bool) -> a -> Bool Source #

Deprecated: Use isReflexive.

Deprecated: use isReflexive.

irreflexive :: (a -> a -> Bool) -> a -> Bool Source #

Deprecated: Use isIrreflexive.

Deprecated: use isIrreflexive.

symmetric :: (a -> a -> Bool) -> a -> a -> Bool Source #

Deprecated: Use isSymmetric.

Deprecated: use isSymmetric.

asymmetric :: (a -> a -> Bool) -> a -> a -> Bool Source #

Deprecated: Use isAsymmetric.

Deprecated: use isAsymmetric.

antisymmetric :: Eq a => (a -> a -> Bool) -> a -> a -> Bool Source #

Deprecated: Use isAntisymmetric.

Deprecated: use isAntisymmetric.

equivalence :: (a -> a -> Bool) -> a -> a -> a -> Bool Source #

Deprecated: Use isEquivalence.

Deprecated: use isEquivalence.

partialOrder :: Eq a => (a -> a -> Bool) -> a -> a -> a -> Bool Source #

Deprecated: Use isPartialOrder.

Deprecated: use isPartialOrder.

strictPartialOrder :: (a -> a -> Bool) -> a -> a -> a -> Bool Source #

Deprecated: Use isStrictPartialOrder.

Deprecated: use isStrictPartialOrder.

totalOrder :: Eq a => (a -> a -> Bool) -> a -> a -> a -> Bool Source #

Deprecated: Use isTotalOrder.

Deprecated: use isTotalOrder.

strictTotalOrder :: Eq a => (a -> a -> Bool) -> a -> a -> a -> Bool Source #

Deprecated: Use isStrictTotalOrder.

Deprecated: use isStrictTotalOrder.

comparison :: (a -> a -> Ordering) -> a -> a -> a -> Bool Source #

Deprecated: Use isComparison.

Deprecated: use isComparison.