{-# LANGUAGE ScopedTypeVariables #-}

{-# OPTIONS_GHC -Wall #-}

module Test.QuickCheck.Classes.Num
  ( numLaws
  ) where

import Data.Proxy (Proxy)
import Test.QuickCheck hiding ((.&.))
import Test.QuickCheck.Property (Property)

import Test.QuickCheck.Classes.Internal (Laws(..), myForAllShrink)

-- | Tests the following properties:
--
-- [/Additive Commutativity/]
--   @a + b ≡ b + a@
-- [/Additive Left Identity/]
--   @0 + a ≡ a@
-- [/Additive Right Identity/]
--   @a + 0 ≡ a@
-- [/Multiplicative Associativity/]
--   @a * (b * c) ≡ (a * b) * c@
-- [/Multiplicative Left Identity/]
--   @1 * a ≡ a@
-- [/Multiplicative Right Identity/]
--   @a * 1 ≡ a@
-- [/Multiplication Left Distributes Over Addition/]
--   @a * (b + c) ≡ (a * b) + (a * c)@
-- [/Multiplication Right Distributes Over Addition/]
--   @(a + b) * c ≡ (a * c) + (b * c)@
-- [/Multiplicative Left Annihilation/]
--   @0 * a ≡ 0@
-- [/Multiplicative Right Annihilation/]
--   @a * 0 ≡ 0@
-- [/Additive Inverse/]
--   @'negate' a '+' a ≡ 0@
-- [/Subtraction/]
--   @a '+' 'negate' b ≡ a '-' b@
-- [/Abs Is Idempotent/]
--   @'abs' ('abs' a) ≡ 'abs' a
-- [/Signum Is Idempotent/]
--   @'signum' ('signum' a) ≡ 'signum' a
-- [/Product Of Abs And Signum Is Id/]
--   @'abs' a * 'signum' a ≡ a@
numLaws :: (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Laws
numLaws :: Proxy a -> Laws
numLaws p :: Proxy a
p = String -> [(String, Property)] -> Laws
Laws "Num"
  [ ("Additive Commutativity", Proxy a -> Property
forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
numCommutativePlus Proxy a
p)
  , ("Additive Left Identity", Proxy a -> Property
forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
numLeftIdentityPlus Proxy a
p)
  , ("Additive Right Identity", Proxy a -> Property
forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
numRightIdentityPlus Proxy a
p)
  , ("Multiplicative Associativity", Proxy a -> Property
forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
numAssociativeTimes Proxy a
p)
  , ("Multiplicative Left Identity", Proxy a -> Property
forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
numLeftIdentityTimes Proxy a
p)
  , ("Multiplicative Right Identity", Proxy a -> Property
forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
numRightIdentityTimes Proxy a
p)
  , ("Multiplication Left Distributes Over Addition", Proxy a -> Property
forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
numLeftMultiplicationDistributes Proxy a
p)
  , ("Multiplication Right Distributes Over Addition", Proxy a -> Property
forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
numRightMultiplicationDistributes Proxy a
p)
  , ("Multiplicative Left Annihilation", Proxy a -> Property
forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
numLeftAnnihilation Proxy a
p)
  , ("Multiplicative Right Annihilation", Proxy a -> Property
forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
numRightAnnihilation Proxy a
p)
  , ("Additive Inverse", Proxy a -> Property
forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
numAdditiveInverse Proxy a
p)
  , ("Subtraction", Proxy a -> Property
forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
numSubtraction Proxy a
p)
  , ("Abs Is Idempotent", Proxy a -> Property
forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
absIdempotence Proxy a
p)
  , ("Signum Is Idempotent", Proxy a -> Property
forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
signumIdempotence Proxy a
p)
  , ("Product Of Abs And Signum Is Id", Proxy a -> Property
forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
absSignumId Proxy a
p)
  ]

numLeftMultiplicationDistributes :: forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
numLeftMultiplicationDistributes :: Proxy a -> Property
numLeftMultiplicationDistributes _ = Bool
-> ((a, a, a) -> Bool)
-> ((a, a, a) -> [String])
-> String
-> ((a, a, a) -> a)
-> String
-> ((a, a, a) -> a)
-> Property
forall a b.
(Arbitrary a, Show b, Eq b) =>
Bool
-> (a -> Bool)
-> (a -> [String])
-> String
-> (a -> b)
-> String
-> (a -> b)
-> Property
myForAllShrink Bool
True (Bool -> (a, a, a) -> Bool
forall a b. a -> b -> a
const Bool
True)
  (\(a
a :: a,b :: a
b,c :: a
c) -> ["a = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
a, "b = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
b, "c = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
c])
  "a * (b + c)"
  (\(a :: a
a,b :: a
b,c :: a
c) -> a
a a -> a -> a
forall a. Num a => a -> a -> a
* (a
b a -> a -> a
forall a. Num a => a -> a -> a
+ a
c))
  "(a * b) + (a * c)"
  (\(a :: a
a,b :: a
b,c :: a
c) -> (a
a a -> a -> a
forall a. Num a => a -> a -> a
* a
b) a -> a -> a
forall a. Num a => a -> a -> a
+ (a
a a -> a -> a
forall a. Num a => a -> a -> a
* a
c))

numRightMultiplicationDistributes :: forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
numRightMultiplicationDistributes :: Proxy a -> Property
numRightMultiplicationDistributes _ = Bool
-> ((a, a, a) -> Bool)
-> ((a, a, a) -> [String])
-> String
-> ((a, a, a) -> a)
-> String
-> ((a, a, a) -> a)
-> Property
forall a b.
(Arbitrary a, Show b, Eq b) =>
Bool
-> (a -> Bool)
-> (a -> [String])
-> String
-> (a -> b)
-> String
-> (a -> b)
-> Property
myForAllShrink Bool
True (Bool -> (a, a, a) -> Bool
forall a b. a -> b -> a
const Bool
True)
  (\(a
a :: a,b :: a
b,c :: a
c) -> ["a = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
a, "b = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
b, "c = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
c])
  "(a + b) * c"
  (\(a :: a
a,b :: a
b,c :: a
c) -> (a
a a -> a -> a
forall a. Num a => a -> a -> a
+ a
b) a -> a -> a
forall a. Num a => a -> a -> a
* a
c)
  "(a * c) + (b * c)"
  (\(a :: a
a,b :: a
b,c :: a
c) -> (a
a a -> a -> a
forall a. Num a => a -> a -> a
* a
c) a -> a -> a
forall a. Num a => a -> a -> a
+ (a
b a -> a -> a
forall a. Num a => a -> a -> a
* a
c))

numLeftIdentityPlus :: forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
numLeftIdentityPlus :: Proxy a -> Property
numLeftIdentityPlus _ = Bool
-> (a -> Bool)
-> (a -> [String])
-> String
-> (a -> a)
-> String
-> (a -> a)
-> Property
forall a b.
(Arbitrary a, Show b, Eq b) =>
Bool
-> (a -> Bool)
-> (a -> [String])
-> String
-> (a -> b)
-> String
-> (a -> b)
-> Property
myForAllShrink Bool
False (Bool -> a -> Bool
forall a b. a -> b -> a
const Bool
True)
  (\(a
a :: a) -> ["a = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
a])
  "0 + a"
  (\a :: a
a -> 0 a -> a -> a
forall a. Num a => a -> a -> a
+ a
a)
  "a"
  (\a :: a
a -> a
a)

numRightIdentityPlus :: forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
numRightIdentityPlus :: Proxy a -> Property
numRightIdentityPlus _ = Bool
-> (a -> Bool)
-> (a -> [String])
-> String
-> (a -> a)
-> String
-> (a -> a)
-> Property
forall a b.
(Arbitrary a, Show b, Eq b) =>
Bool
-> (a -> Bool)
-> (a -> [String])
-> String
-> (a -> b)
-> String
-> (a -> b)
-> Property
myForAllShrink Bool
False (Bool -> a -> Bool
forall a b. a -> b -> a
const Bool
True)
  (\(a
a :: a) -> ["a = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
a])
  "a + 0"
  (\a :: a
a -> a
a a -> a -> a
forall a. Num a => a -> a -> a
+ 0)
  "a"
  (\a :: a
a -> a
a)

numRightIdentityTimes :: forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
numRightIdentityTimes :: Proxy a -> Property
numRightIdentityTimes _ = Bool
-> (a -> Bool)
-> (a -> [String])
-> String
-> (a -> a)
-> String
-> (a -> a)
-> Property
forall a b.
(Arbitrary a, Show b, Eq b) =>
Bool
-> (a -> Bool)
-> (a -> [String])
-> String
-> (a -> b)
-> String
-> (a -> b)
-> Property
myForAllShrink Bool
False (Bool -> a -> Bool
forall a b. a -> b -> a
const Bool
True)
  (\(a
a :: a) -> ["a = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
a])
  "a * 1"
  (\a :: a
a -> a
a a -> a -> a
forall a. Num a => a -> a -> a
* 1)
  "a"
  (\a :: a
a -> a
a)

numLeftIdentityTimes :: forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
numLeftIdentityTimes :: Proxy a -> Property
numLeftIdentityTimes _ = Bool
-> (a -> Bool)
-> (a -> [String])
-> String
-> (a -> a)
-> String
-> (a -> a)
-> Property
forall a b.
(Arbitrary a, Show b, Eq b) =>
Bool
-> (a -> Bool)
-> (a -> [String])
-> String
-> (a -> b)
-> String
-> (a -> b)
-> Property
myForAllShrink Bool
False (Bool -> a -> Bool
forall a b. a -> b -> a
const Bool
True)
  (\(a
a :: a) -> ["a = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
a])
  "1 * a"
  (\a :: a
a -> 1 a -> a -> a
forall a. Num a => a -> a -> a
* a
a)
  "a"
  (\a :: a
a -> a
a)

numLeftAnnihilation :: forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
numLeftAnnihilation :: Proxy a -> Property
numLeftAnnihilation _ = Bool
-> (a -> Bool)
-> (a -> [String])
-> String
-> (a -> a)
-> String
-> (a -> a)
-> Property
forall a b.
(Arbitrary a, Show b, Eq b) =>
Bool
-> (a -> Bool)
-> (a -> [String])
-> String
-> (a -> b)
-> String
-> (a -> b)
-> Property
myForAllShrink Bool
False (Bool -> a -> Bool
forall a b. a -> b -> a
const Bool
True)
  (\(a
a :: a) -> ["a = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
a])
  "0 * a"
  (\a :: a
a -> 0 a -> a -> a
forall a. Num a => a -> a -> a
* a
a)
  "0"
  (\_ -> 0)

numRightAnnihilation :: forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
numRightAnnihilation :: Proxy a -> Property
numRightAnnihilation _ = Bool
-> (a -> Bool)
-> (a -> [String])
-> String
-> (a -> a)
-> String
-> (a -> a)
-> Property
forall a b.
(Arbitrary a, Show b, Eq b) =>
Bool
-> (a -> Bool)
-> (a -> [String])
-> String
-> (a -> b)
-> String
-> (a -> b)
-> Property
myForAllShrink Bool
False (Bool -> a -> Bool
forall a b. a -> b -> a
const Bool
True)
  (\(a
a :: a) -> ["a = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
a])
  "a * 0"
  (\a :: a
a -> a
a a -> a -> a
forall a. Num a => a -> a -> a
* 0)
  "0"
  (\_ -> 0)

numCommutativePlus :: forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
numCommutativePlus :: Proxy a -> Property
numCommutativePlus _ = Bool
-> ((a, a) -> Bool)
-> ((a, a) -> [String])
-> String
-> ((a, a) -> a)
-> String
-> ((a, a) -> a)
-> Property
forall a b.
(Arbitrary a, Show b, Eq b) =>
Bool
-> (a -> Bool)
-> (a -> [String])
-> String
-> (a -> b)
-> String
-> (a -> b)
-> Property
myForAllShrink Bool
True (Bool -> (a, a) -> Bool
forall a b. a -> b -> a
const Bool
True)
  (\(a
a :: a,b :: a
b) -> ["a = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
a, "b = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
b])
  "a + b"
  (\(a :: a
a,b :: a
b) -> a
a a -> a -> a
forall a. Num a => a -> a -> a
+ a
b)
  "b + a"
  (\(a :: a
a,b :: a
b) -> a
b a -> a -> a
forall a. Num a => a -> a -> a
+ a
a)

numAssociativeTimes :: forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
numAssociativeTimes :: Proxy a -> Property
numAssociativeTimes _ = Bool
-> ((a, a, a) -> Bool)
-> ((a, a, a) -> [String])
-> String
-> ((a, a, a) -> a)
-> String
-> ((a, a, a) -> a)
-> Property
forall a b.
(Arbitrary a, Show b, Eq b) =>
Bool
-> (a -> Bool)
-> (a -> [String])
-> String
-> (a -> b)
-> String
-> (a -> b)
-> Property
myForAllShrink Bool
True (Bool -> (a, a, a) -> Bool
forall a b. a -> b -> a
const Bool
True)
  (\(a
a :: a,b :: a
b,c :: a
c) -> ["a = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
a, "b = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
b, "c = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
c])
  "a * (b * c)"
  (\(a :: a
a,b :: a
b,c :: a
c) -> a
a a -> a -> a
forall a. Num a => a -> a -> a
* (a
b a -> a -> a
forall a. Num a => a -> a -> a
* a
c))
  "(a * b) * c"
  (\(a :: a
a,b :: a
b,c :: a
c) -> (a
a a -> a -> a
forall a. Num a => a -> a -> a
* a
b) a -> a -> a
forall a. Num a => a -> a -> a
* a
c)

numAdditiveInverse :: forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
numAdditiveInverse :: Proxy a -> Property
numAdditiveInverse _ = Bool
-> (a -> Bool)
-> (a -> [String])
-> String
-> (a -> a)
-> String
-> (a -> a)
-> Property
forall a b.
(Arbitrary a, Show b, Eq b) =>
Bool
-> (a -> Bool)
-> (a -> [String])
-> String
-> (a -> b)
-> String
-> (a -> b)
-> Property
myForAllShrink Bool
True (Bool -> a -> Bool
forall a b. a -> b -> a
const Bool
True)
  (\(a
a :: a) -> ["a = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
a])
  "negate a + a"
  (\a :: a
a -> (-a
a) a -> a -> a
forall a. Num a => a -> a -> a
+ a
a)
  "0"
  (a -> a -> a
forall a b. a -> b -> a
const 0)

numSubtraction :: forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
numSubtraction :: Proxy a -> Property
numSubtraction _ = Bool
-> ((a, a) -> Bool)
-> ((a, a) -> [String])
-> String
-> ((a, a) -> a)
-> String
-> ((a, a) -> a)
-> Property
forall a b.
(Arbitrary a, Show b, Eq b) =>
Bool
-> (a -> Bool)
-> (a -> [String])
-> String
-> (a -> b)
-> String
-> (a -> b)
-> Property
myForAllShrink Bool
True (Bool -> (a, a) -> Bool
forall a b. a -> b -> a
const Bool
True)
  (\(a
a :: a, a
b :: a) -> ["a = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
a, "b = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
b])
  "a + negate b"
  (\(a :: a
a,b :: a
b) -> a
a a -> a -> a
forall a. Num a => a -> a -> a
+ a -> a
forall a. Num a => a -> a
negate a
b)
  "a - b"
  (\(a :: a
a,b :: a
b) -> a
a a -> a -> a
forall a. Num a => a -> a -> a
- a
b)

absIdempotence :: forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
absIdempotence :: Proxy a -> Property
absIdempotence _ = Bool
-> (a -> Bool)
-> (a -> [String])
-> String
-> (a -> a)
-> String
-> (a -> a)
-> Property
forall a b.
(Arbitrary a, Show b, Eq b) =>
Bool
-> (a -> Bool)
-> (a -> [String])
-> String
-> (a -> b)
-> String
-> (a -> b)
-> Property
myForAllShrink Bool
True (Bool -> a -> Bool
forall a b. a -> b -> a
const Bool
True)
  (\(a
a :: a) -> ["a = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
a])
  "abs (abs a)"
  (a -> a
forall a. Num a => a -> a
abs (a -> a) -> (a -> a) -> a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a
forall a. Num a => a -> a
abs)
  "abs a"
  a -> a
forall a. Num a => a -> a
abs

signumIdempotence :: forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
signumIdempotence :: Proxy a -> Property
signumIdempotence _ = Bool
-> (a -> Bool)
-> (a -> [String])
-> String
-> (a -> a)
-> String
-> (a -> a)
-> Property
forall a b.
(Arbitrary a, Show b, Eq b) =>
Bool
-> (a -> Bool)
-> (a -> [String])
-> String
-> (a -> b)
-> String
-> (a -> b)
-> Property
myForAllShrink Bool
True (Bool -> a -> Bool
forall a b. a -> b -> a
const Bool
True)
  (\(a
a :: a) -> ["a = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
a])
  "signum (signum a)"
  (a -> a
forall a. Num a => a -> a
signum (a -> a) -> (a -> a) -> a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a
forall a. Num a => a -> a
signum)
  "signum a"
  a -> a
forall a. Num a => a -> a
signum

absSignumId :: forall a. (Num a, Eq a, Arbitrary a, Show a) => Proxy a -> Property
absSignumId :: Proxy a -> Property
absSignumId _ = Bool
-> (a -> Bool)
-> (a -> [String])
-> String
-> (a -> a)
-> String
-> (a -> a)
-> Property
forall a b.
(Arbitrary a, Show b, Eq b) =>
Bool
-> (a -> Bool)
-> (a -> [String])
-> String
-> (a -> b)
-> String
-> (a -> b)
-> Property
myForAllShrink Bool
True (Bool -> a -> Bool
forall a b. a -> b -> a
const Bool
True)
  (\(a
a :: a) -> ["a = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
a])
  "abs a * signum a"
  (\a :: a
a -> a -> a
forall a. Num a => a -> a
abs a
a a -> a -> a
forall a. Num a => a -> a -> a
* a -> a
forall a. Num a => a -> a
signum a
a)
  "a"
  a -> a
forall a. a -> a
id