Copyright | (c) 2015-2024 Rudy Matela |
---|---|
License | 3-Clause BSD (see the file LICENSE) |
Maintainer | Rudy Matela <rudy@matela.com.br> |
Safe Haskell | Safe-Inferred |
Language | Haskell2010 |
This module is part of LeanCheck, a simple enumerative property-based testing library.
Some operators for property-based testing.
Synopsis
- (==>) :: Bool -> Bool -> Bool
- (===) :: Eq b => (a -> b) -> (a -> b) -> a -> Bool
- (====) :: Eq c => (a -> b -> c) -> (a -> b -> c) -> a -> b -> Bool
- (&&&) :: (a -> Bool) -> (a -> Bool) -> a -> Bool
- (&&&&) :: (a -> b -> Bool) -> (a -> b -> Bool) -> a -> b -> Bool
- (&&&&&) :: (a -> b -> c -> Bool) -> (a -> b -> c -> Bool) -> a -> b -> c -> Bool
- (|||) :: (a -> Bool) -> (a -> Bool) -> a -> Bool
- (||||) :: (a -> b -> Bool) -> (a -> b -> Bool) -> a -> b -> Bool
- isIdempotent :: Eq a => (a -> a) -> a -> Bool
- isIdentity :: Eq a => (a -> a) -> a -> Bool
- isNeverIdentity :: Eq a => (a -> a) -> a -> Bool
- isCommutative :: Eq b => (a -> a -> b) -> a -> a -> Bool
- isAssociative :: Eq a => (a -> a -> a) -> a -> a -> a -> Bool
- isDistributiveOver :: Eq a => (a -> a -> a) -> (a -> a -> a) -> a -> a -> a -> Bool
- isLeftDistributiveOver :: Eq a => (a -> a -> a) -> (a -> a -> a) -> a -> a -> a -> Bool
- isRightDistributiveOver :: Eq a => (a -> a -> a) -> (a -> a -> a) -> a -> a -> a -> Bool
- isFlipped :: Eq c => (a -> b -> c) -> (b -> a -> c) -> a -> b -> Bool
- isTransitive :: (a -> a -> Bool) -> a -> a -> a -> Bool
- isReflexive :: (a -> a -> Bool) -> a -> Bool
- isIrreflexive :: (a -> a -> Bool) -> a -> Bool
- isSymmetric :: (a -> a -> Bool) -> a -> a -> Bool
- isAsymmetric :: (a -> a -> Bool) -> a -> a -> Bool
- isAntisymmetric :: Eq a => (a -> a -> Bool) -> a -> a -> Bool
- isEquivalence :: (a -> a -> Bool) -> a -> a -> a -> Bool
- isPartialOrder :: Eq a => (a -> a -> Bool) -> a -> a -> a -> Bool
- isStrictPartialOrder :: (a -> a -> Bool) -> a -> a -> a -> Bool
- isTotalOrder :: Eq a => (a -> a -> Bool) -> a -> a -> a -> Bool
- isStrictTotalOrder :: Eq a => (a -> a -> Bool) -> a -> a -> a -> Bool
- isComparison :: (a -> a -> Ordering) -> a -> a -> a -> Bool
- (=$) :: Eq b => a -> (a -> b) -> a -> Bool
- ($=) :: (a -> Bool) -> a -> Bool
- (=|) :: Eq a => [a] -> Int -> [a] -> Bool
- (|=) :: (a -> Bool) -> a -> Bool
- okEq :: Eq a => a -> a -> a -> Bool
- okOrd :: Ord a => a -> a -> a -> Bool
- okEqOrd :: (Eq a, Ord a) => a -> a -> a -> Bool
- okNum :: (Eq a, Num a) => a -> a -> a -> Bool
- okNumNonNegative :: (Eq a, Num a) => a -> a -> a -> Bool
- idempotent :: Eq a => (a -> a) -> a -> Bool
- identity :: Eq a => (a -> a) -> a -> Bool
- neverIdentity :: Eq a => (a -> a) -> a -> Bool
- commutative :: Eq b => (a -> a -> b) -> a -> a -> Bool
- associative :: Eq a => (a -> a -> a) -> a -> a -> a -> Bool
- distributive :: Eq a => (a -> a -> a) -> (a -> a -> a) -> a -> a -> a -> Bool
- symmetric2 :: Eq c => (a -> b -> c) -> (b -> a -> c) -> a -> b -> Bool
- transitive :: (a -> a -> Bool) -> a -> a -> a -> Bool
- reflexive :: (a -> a -> Bool) -> a -> Bool
- irreflexive :: (a -> a -> Bool) -> a -> Bool
- symmetric :: (a -> a -> Bool) -> a -> a -> Bool
- asymmetric :: (a -> a -> Bool) -> a -> a -> Bool
- antisymmetric :: Eq a => (a -> a -> Bool) -> a -> a -> Bool
- equivalence :: (a -> a -> Bool) -> a -> a -> a -> Bool
- partialOrder :: Eq a => (a -> a -> Bool) -> a -> a -> a -> Bool
- strictPartialOrder :: (a -> a -> Bool) -> a -> a -> a -> Bool
- totalOrder :: Eq a => (a -> a -> Bool) -> a -> a -> a -> Bool
- strictTotalOrder :: Eq a => (a -> a -> Bool) -> a -> a -> a -> Bool
- comparison :: (a -> a -> Ordering) -> a -> a -> a -> Bool
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 flip
ped 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 #
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
(=|) :: 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
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).
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):
- 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
.