{-# LANGUAGE ScopedTypeVariables #-}
{-# OPTIONS_GHC -Wall #-}
module Test.QuickCheck.Classes.Semigroup
(
semigroupLaws
, commutativeSemigroupLaws
, exponentialSemigroupLaws
, idempotentSemigroupLaws
, rectangularBandSemigroupLaws
) where
import Prelude hiding (foldr1)
import Data.Semigroup (Semigroup(..))
import Data.Proxy (Proxy)
import Test.QuickCheck hiding ((.&.))
import Test.QuickCheck.Property (Property)
import Test.QuickCheck.Classes.Common (Laws(..), SmallList(..), myForAllShrink)
import Data.Foldable (foldr1,toList)
import Data.List.NonEmpty (NonEmpty((:|)))
import qualified Data.List as L
semigroupLaws :: (Semigroup a, Eq a, Arbitrary a, Show a) => Proxy a -> Laws
semigroupLaws p = Laws "Semigroup"
[ ("Associative", semigroupAssociative p)
, ("Concatenation", semigroupConcatenation p)
, ("Times", semigroupTimes p)
]
commutativeSemigroupLaws :: (Semigroup a, Eq a, Arbitrary a, Show a) => Proxy a -> Laws
commutativeSemigroupLaws p = Laws "Commutative Semigroup"
[ ("Commutative", semigroupCommutative p)
]
idempotentSemigroupLaws :: (Semigroup a, Eq a, Arbitrary a, Show a) => Proxy a -> Laws
idempotentSemigroupLaws p = Laws "Idempotent Semigroup"
[ ("Idempotent", semigroupIdempotent p)
]
rectangularBandSemigroupLaws :: (Semigroup a, Eq a, Arbitrary a, Show a) => Proxy a -> Laws
rectangularBandSemigroupLaws p = Laws "Rectangular Band Semigroup"
[ ("Rectangular Band", semigroupRectangularBand p)
]
exponentialSemigroupLaws :: (Semigroup a, Eq a, Arbitrary a, Show a) => Proxy a -> Laws
exponentialSemigroupLaws p = Laws "Exponential Semigroup"
[ ("Exponential", semigroupExponential p)
]
semigroupAssociative :: forall a. (Semigroup a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
semigroupAssociative _ = myForAllShrink True (const True)
(\(a :: a,b,c) -> ["a = " ++ show a, "b = " ++ show b, "c = " ++ show c])
"a <> (b <> c)"
(\(a,b,c) -> a <> (b <> c))
"(a <> b) <> c"
(\(a,b,c) -> (a <> b) <> c)
semigroupCommutative :: forall a. (Semigroup a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
semigroupCommutative _ = myForAllShrink True (const True)
(\(a :: a,b) -> ["a = " ++ show a, "b = " ++ show b])
"a <> b"
(\(a,b) -> a <> b)
"b <> a"
(\(a,b) -> b <> a)
semigroupConcatenation :: forall a. (Semigroup a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
semigroupConcatenation _ = myForAllShrink True (const True)
(\(a, SmallList (as :: [a])) -> ["as = " ++ show (a :| as)])
"sconcat as"
(\(a, SmallList as) -> sconcat (a :| as))
"foldr1 (<>) as"
(\(a, SmallList as) -> foldr1 (<>) (a :| as))
semigroupTimes :: forall a. (Semigroup a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
semigroupTimes _ = myForAllShrink True (\(_,n) -> n > 0)
(\(a :: a, n :: Int) -> ["a = " ++ show a, "n = " ++ show n])
"stimes n a"
(\(a,n) -> stimes n a)
"foldr1 (<>) (replicate n a)"
(\(a,n) -> foldr1 (<>) (replicate n a))
semigroupExponential :: forall a. (Semigroup a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
semigroupExponential _ = myForAllShrink True (\(_,_,n) -> n > 0)
(\(a :: a, b, n :: Int) -> ["a = " ++ show a, "b = " ++ show b, "n = " ++ show n])
"stimes n (a <> b)"
(\(a,b,n) -> stimes n (a <> b))
"stimes n a <> stimes n b"
(\(a,b,n) -> stimes n a <> stimes n b)
semigroupIdempotent :: forall a. (Semigroup a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
semigroupIdempotent _ = myForAllShrink False (const True)
(\(a :: a) -> ["a = " ++ show a])
"a <> a"
(\a -> a <> a)
"a"
(\a -> a)
semigroupRectangularBand :: forall a. (Semigroup a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
semigroupRectangularBand _ = myForAllShrink False (const True)
(\(a :: a, b) -> ["a = " ++ show a, "b = " ++ show b])
"a <> b <> a"
(\(a,b) -> a <> b <> a)
"a"
(\(a,_) -> a)