{-# language CPP #-} {-# language ScopedTypeVariables #-} {-# language RankNTypes #-} #ifndef HAVE_SEMIRINGS module Hedgehog.Classes.Semiring () where #else module Hedgehog.Classes.Semiring (semiringLaws, ringLaws, starLaws) where import Hedgehog import Hedgehog.Classes.Common import Prelude hiding (Num(..)) import Data.Semiring import Data.Star -- | Tests the following 'Semiring' laws: -- -- [__Additive Left Identity__]: @'zero' '+' x@ ≡ @x@ -- [__Additive Right Identity__]: @x '+' 'zero'@ ≡ @x@ -- [__Additive Associativity__]: @x '+' (y '+' z)@ ≡ @(x '+' y) '+' z@ -- [__Additive Commutativity__]: @x '+' y@ ≡ @y '+' x@ -- [__Multiplicative Left Identity__]: @'one' '*' x@ ≡ @x@ -- [__Multiplicative Right Identity__]: @x '*' 'one'@ ≡ @x@ -- [__Multiplicative Associativity__]: @x '*' (y '*' z)@ ≡ @(x '*' y) '*' z@ -- [__Multiplicatiion Left-Distributes Over Addtion__]: @x '*' (y '+' z)@ ≡ @(x '*' y) '+' (x '*' z)@ -- [__Multiplication Right-Distibutes Over Addition__]: @(y '+' z) '*' x@ ≡ @(y '*' x) '+' (z '*' x)@ -- [__Multiplicative Left Annihilation__]: @'zero' '*' x@ ≡ @'zero'@ -- [__Multiplicative Right Annihilation__]: @x '*' 'zero'@ ≡ @'zero'@ semiringLaws :: (Semiring a, Eq a, Show a) => Gen a -> Laws semiringLaws gen = Laws "Semiring" [ ("Additive Left Identity", semiringAdditiveLeftIdentity gen) , ("Additive Right Identity", semiringAdditiveRightIdentity gen) , ("Additive Associativity", semiringAdditiveAssociativity gen) , ("Additive Commutativity", semiringAdditiveCommutativity gen) , ("Multiplicative Left Identity", semiringMultiplicativeLeftIdentity gen) , ("Multiplicative Right Identity", semiringMultiplicativeRightIdentity gen) , ("Multiplicative Associativity", semiringMultiplicativeAssociativity gen) , ("Multiplication Left-Distributes Over Addition", semiringLeftMultiplicationDistributes gen) , ("Multiplication Right-Distributes Over Addition", semiringRightMultiplicationDistributes gen) , ("Multiplicative Left Annihilation", semiringLeftAnnihilation gen) , ("Multiplicative Right Annihilation", semiringRightAnnihilation gen) ] -- | Tests the following 'Ring' laws: -- -- [__Additive Inverse__]: @'negate' x '+' x@ ≡ @'zero'@ ringLaws :: (Ring a, Eq a, Show a) => Gen a -> Laws ringLaws gen = Laws "Ring" [ ("Additive Inverse", ringAdditiveInverse gen) ] -- | Tests the following 'Star' laws: -- -- [__Asteration__]: @'star' x@ ≡ @'one' '+' x '*' 'star' x@ -- [__APlus__]: @'aplus' x@ ≡ @x '*' 'star' x@ starLaws :: (Star a, Eq a, Show a) => Gen a -> Laws starLaws gen = Laws "Star" [ ("Asteration", starAsteration gen) , ("APlus", starAplus gen) ] type SemiringProp a = (Semiring a, Eq a, Show a) => Gen a -> Property type RingProp a = (Ring a, Eq a, Show a) => Gen a -> Property type StarProp a = (Star a, Eq a, Show a) => Gen a -> Property ringAdditiveInverse :: forall a. RingProp a ringAdditiveInverse gen = property $ do a <- forAll gen let lhs = negate a + a let rhs = zero :: a let ctx = contextualise $ LawContext { lawContextLawName = "Additive Inverse", lawContextTcName = "Ring" , lawContextLawBody = "negate a + a" `congruency` "zero" , lawContextTcProp = let showA = show a; showZ = show (zero :: a); in lawWhere [ "negate a + a" `congruency` "zero, where" , "a = " ++ showA , "zero = " ++ showZ ] , lawContextReduced = reduced lhs rhs } heqCtx lhs rhs ctx semiringAdditiveLeftIdentity :: forall a. SemiringProp a semiringAdditiveLeftIdentity gen = property $ do x <- forAll gen let lhs = zero + x let rhs = x let ctx = contextualise $ LawContext { lawContextLawName = "Additive Left Identity", lawContextTcName = "Semiring" , lawContextLawBody = "zero + x" `congruency` "x" , lawContextReduced = reduced lhs rhs , lawContextTcProp = let showX = show x; showZ = show (zero :: a); in lawWhere [ "zero + x" `congruency` "x, where" , "x = " ++ showX , "zero = " ++ showZ ] } heqCtx lhs rhs ctx semiringAdditiveRightIdentity :: forall a. SemiringProp a semiringAdditiveRightIdentity gen = property $ do x <- forAll gen let lhs = x + zero let rhs = x let ctx = contextualise $ LawContext { lawContextLawName = "Additive Right Identity", lawContextTcName = "Semiring" , lawContextLawBody = "x + zero" `congruency` "x" , lawContextReduced = reduced lhs rhs , lawContextTcProp = let showX = show x; showZ = show (zero :: a); in lawWhere [ "x + zero" `congruency` "x, where" , "x = " ++ showX , "zero = " ++ showZ ] } heqCtx lhs rhs ctx semiringAdditiveAssociativity :: forall a. SemiringProp a semiringAdditiveAssociativity gen = property $ do a <- forAll gen b <- forAll gen c <- forAll gen let lhs = a + (b + c) let rhs = (a + b) + c let ctx = contextualise $ LawContext { lawContextLawName = "Additive Associativity", lawContextTcName = "Semiring" , lawContextLawBody = "x + (y + z)" `congruency` "(x + y) + z" , lawContextReduced = reduced lhs rhs , lawContextTcProp = let showX = show a; showY = show b; showZ = show c; in lawWhere [ "x + (y + z)" `congruency` "(x + y) + z, where" , "x = " ++ showX , "y = " ++ showY , "z = " ++ showZ ] } heqCtx lhs rhs ctx semiringAdditiveCommutativity :: forall a. SemiringProp a semiringAdditiveCommutativity gen = property $ do a <- forAll gen b <- forAll gen let lhs = a + b let rhs = b + a let ctx = contextualise $ LawContext { lawContextLawName = "Additive Commutativity", lawContextTcName = "Semiring" , lawContextLawBody = "x + y" `congruency` "y + x" , lawContextReduced = reduced lhs rhs , lawContextTcProp = let showX = show a; showY = show b; in lawWhere [ "x + y" `congruency` "y + x, where" , "x = " ++ showX , "y = " ++ showY ] } heqCtx lhs rhs ctx semiringMultiplicativeLeftIdentity :: forall a. SemiringProp a semiringMultiplicativeLeftIdentity gen = property $ do x <- forAll gen let lhs = one * x let rhs = x let ctx = contextualise $ LawContext { lawContextLawName = "Multiplicative Left Identity", lawContextTcName = "Semiring" , lawContextLawBody = "one * x" `congruency` "x" , lawContextReduced = reduced lhs rhs , lawContextTcProp = let showX = show x; showO = show (one :: a); in lawWhere [ "one * x" `congruency` "x, where" , "x = " ++ showX , "one = " ++ showO ] } heqCtx lhs rhs ctx semiringMultiplicativeRightIdentity :: forall a. SemiringProp a semiringMultiplicativeRightIdentity gen = property $ do x <- forAll gen let lhs = x * one let rhs = x let ctx = contextualise $ LawContext { lawContextLawName = "Multiplicative Right Identity", lawContextTcName = "Semiring" , lawContextLawBody = "x * one" `congruency` "x" , lawContextReduced = reduced lhs rhs , lawContextTcProp = let showX = show x; showO = show (one :: a); in lawWhere [ "x * one" `congruency` "x, where" , "x = " ++ showX , "one = " ++ showO ] } heqCtx lhs rhs ctx semiringMultiplicativeAssociativity :: forall a. SemiringProp a semiringMultiplicativeAssociativity gen = property $ do a <- forAll gen b <- forAll gen c <- forAll gen let lhs = a * (b * c) let rhs = (a * b) * c let ctx = contextualise $ LawContext { lawContextLawName = "Multiplicative Associativity", lawContextTcName = "Semiring" , lawContextLawBody = "x * (y * z)" `congruency` "(x * y) * z" , lawContextReduced = reduced lhs rhs , lawContextTcProp = let showX = show a; showY = show b; showZ = show c; in lawWhere [ "x * (y * z)" `congruency` "(x * y) * z, where" , "x = " ++ showX , "y = " ++ showY , "z = " ++ showZ ] } heqCtx lhs rhs ctx semiringLeftMultiplicationDistributes :: forall a. SemiringProp a semiringLeftMultiplicationDistributes gen = property $ do a <- forAll gen b <- forAll gen c <- forAll gen let lhs = a * (b + c) let rhs = (a * b) + (a * c) let ctx = contextualise $ LawContext { lawContextLawName = "Multiplication Left-Distributes Over Addition", lawContextTcName = "Semiring" , lawContextLawBody = "x * (y + z)" `congruency` "(x * y) + (x * z)" , lawContextReduced = reduced lhs rhs , lawContextTcProp = let showX = show a; showY = show b; showZ = show c; in lawWhere [ "x * (y + z)" `congruency` "(x * y) + (x * z), where" , "x = " ++ showX , "y = " ++ showY , "z = " ++ showZ ] } heqCtx lhs rhs ctx semiringRightMultiplicationDistributes :: forall a. SemiringProp a semiringRightMultiplicationDistributes gen = property $ do a <- forAll gen b <- forAll gen c <- forAll gen let lhs = (a + b) * c let rhs = (a * c) + (b * c) let ctx = contextualise $ LawContext { lawContextLawName = "Multiplication Right-Distributes Over Addition", lawContextTcName = "Semiring" , lawContextLawBody = "(y + z) * x" `congruency` "(y * x) + (z * x)" , lawContextReduced = reduced lhs rhs , lawContextTcProp = let showX = show a; showY = show b; showZ = show c; in lawWhere [ "(y + z) * x" `congruency` "(y * x) + (z * x), where" , "x = " ++ showX , "y = " ++ showY , "z = " ++ showZ ] } heqCtx lhs rhs ctx semiringLeftAnnihilation :: forall a. SemiringProp a semiringLeftAnnihilation gen = property $ do x <- forAll gen let lhs = zero * x let rhs = zero let ctx = contextualise $ LawContext { lawContextLawName = "Multiplicative Left Annihilation", lawContextTcName = "Semiring" , lawContextLawBody = "zero * x" `congruency` "zero" , lawContextReduced = reduced lhs rhs , lawContextTcProp = let showX = show x; showZ = show (zero :: a); in lawWhere [ "zero * x" `congruency` "zero, where" , "x = " ++ showX , "zero = " ++ showZ ] } heqCtx lhs rhs ctx semiringRightAnnihilation :: forall a. SemiringProp a semiringRightAnnihilation gen = property $ do x <- forAll gen let lhs = x * zero let rhs = zero let ctx = contextualise $ LawContext { lawContextLawName = "Multiplicative Right Annihilation", lawContextTcName = "Semiring" , lawContextLawBody = "x * zero" `congruency` "zero" , lawContextReduced = reduced lhs rhs , lawContextTcProp = let showX = show x; showZ = show (zero :: a); in lawWhere [ "x * zero" `congruency` "zero, where" , "x = " ++ showX , "zero = " ++ showZ ] } heqCtx lhs rhs ctx starAsteration :: forall a. StarProp a starAsteration gen = property $ do x <- forAll gen let lhs = star x let rhs = one + x * star x let ctx = contextualise $ LawContext { lawContextLawName = "Asteration", lawContextTcName = "Star" , lawContextLawBody = "star x" `congruency` "one + x * star x" , lawContextReduced = reduced lhs rhs , lawContextTcProp = let showX = show x; showOne = show (one :: a); in lawWhere [ "star x" `congruency` "one + x * star x, where" , "x = " ++ showX , "one = " ++ showOne ] } heqCtx lhs rhs ctx starAplus :: forall a. StarProp a starAplus gen = property $ do x <- forAll gen let lhs = aplus x let rhs = x * star x let ctx = contextualise $ LawContext { lawContextLawName = "APlus", lawContextTcName = "Star" , lawContextLawBody = "aplus x" `congruency` "x * star x" , lawContextReduced = reduced lhs rhs , lawContextTcProp = let showX = show x in lawWhere [ "aplus x" `congruency` "x * star x, where" , "x = " ++ showX ] } heqCtx lhs rhs ctx #endif