bv-little-1.3.0: util/Operator/Binary/Comparison.hs
{-|
Copyright : © 2020 Alex Washburn
License : BSD-3-Clause
Maintainer : github@recursion.ninja
Stability : Stable
-}
{-# Language BangPatterns #-}
{-# Language DeriveAnyClass #-}
{-# Language DeriveGeneric #-}
{-# Language DerivingStrategies #-}
{-# Language FlexibleInstances #-}
{-# Language MultiParamTypeClasses #-}
{-# Language Safe #-}
module Operator.Binary.Comparison
( ComparisonOperator (getComparator)
) where
import Control.DeepSeq
import Data.List (elemIndex)
import Data.Maybe (fromJust)
import Data.Monoid ()
import GHC.Generics
import Test.QuickCheck hiding (generate)
import Test.SmallCheck.Series
{-|
Representation of all possible binary operators of type @(Bool -> Bool -> Bool)@.
Useful for both property and enumeration based testing.
-}
newtype ComparisonOperator
= CO { getComparator :: Bool -> Bool -> Ordering }
deriving anyclass (NFData)
deriving stock (Generic)
comparatorList :: [ComparisonOperator]
comparatorList = do
w <- [minBound .. maxBound]
x <- [minBound .. maxBound]
y <- [minBound .. maxBound]
z <- [minBound .. maxBound]
pure
$ let
op False False = w
op False True = x
op True False = y
op True True = z
in CO op
instance Arbitrary ComparisonOperator where
arbitrary = arbitraryBoundedEnum
instance Bounded ComparisonOperator where
minBound = head comparatorList
maxBound = last comparatorList
instance CoArbitrary ComparisonOperator where
coarbitrary = coarbitraryEnum
instance Enum ComparisonOperator where
toEnum n = let !i = n `quot` length comparatorList in comparatorList !! i
fromEnum c = fromJust $ elemIndex c comparatorList
instance Eq ComparisonOperator where
(CO f) == (CO g) = and
[ f False False == g False False
, f False True == g False True
, f True False == g True False
, f True True == g True True
]
instance Monad m => Serial m ComparisonOperator where
series = generate $ const comparatorList
instance Show ComparisonOperator where
show (CO f) = unlines
[ ""
, "f / F F -> " <> show (f False False)
, " | F T -> " <> show (f False True)
, " | T F -> " <> show (f True False)
, " \\ T T -> " <> show (f True True)
]