packages feed

spectacle-1.0.0: test/unit-tests/Test/Laws/Ord.hs

-- | Laws for total orders.
--
-- @since 0.1.0.0
module Test.Laws.Ord
  ( -- * Ord Laws
    laws,
    irreflexive,
    antisymmetry,
  )
where

import Hedgehog (Gen, PropertyT, assert, failure, footnote, forAll, property, success, withTests)
import Test.Tasty (TestTree, testGroup)
import Test.Tasty.Hedgehog (testProperty)

-- ---------------------------------------------------------------------------------------------------------------------

laws :: (Show a, Ord a) => String -> Gen a -> TestTree
laws desc gen =
  testGroup
    (if null desc then "ord laws" else desc ++ " - ord laws")
    [ testProperty "1. antisymmetry" $ property (antisymmetry gen)
    , testProperty "2. irreflexive" . withTests 1 $ property (irreflexive gen)
    ]

-- | Strict order is irreflexive
--
-- @
-- a < b <=> a /= b
-- @
irreflexive :: (Monad m, Show a, Ord a) => Gen a -> PropertyT m ()
irreflexive gen = do
  a <- forAll gen
  footnote (show a ++ " < " ++ show a)
  if a < a
    then failure
    else success

-- | Strict order is antisymmetric
--
-- @
-- a < b <=> not (b < a)
-- @
antisymmetry :: (Monad m, Show a, Ord a) => Gen a -> PropertyT m ()
antisymmetry gen = do
  a <- forAll gen
  b <- forAll gen
  footnote (show a ++ " < " ++ show b)
  if a < b
    then assert (b >= a)
    else assert (a >= b)