{-# LANGUAGE ScopedTypeVariables #-}

{-# OPTIONS_GHC -Wall #-}

module Test.QuickCheck.Classes.Integral
  ( integralLaws
  ) 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:
--
-- [/Quotient Remainder/]
--   @(quot x y) * y + (rem x y) ≡ x@
-- [/Division Modulus/]
--   @(div x y) * y + (mod x y) ≡ x@
-- [/Integer Roundtrip/]
--   @fromInteger (toInteger x) ≡ x@
-- [/QuotRem is (Quot, Rem)/]
--   @quotRem x y ≡ (quot x y, rem x y)@
-- [/DivMod is (Div, Mod)/]
--   @divMod x y ≡ (div x y, mod x y)@
integralLaws :: (Integral a, Arbitrary a, Show a) => Proxy a -> Laws
integralLaws :: Proxy a -> Laws
integralLaws Proxy a
p = String -> [(String, Property)] -> Laws
Laws String
"Integral"
  [ (String
"Quotient Remainder", Proxy a -> Property
forall a. (Integral a, Arbitrary a, Show a) => Proxy a -> Property
integralQuotientRemainder Proxy a
p)
  , (String
"Division Modulus", Proxy a -> Property
forall a. (Integral a, Arbitrary a, Show a) => Proxy a -> Property
integralDivisionModulus Proxy a
p)
  , (String
"Integer Roundtrip", Proxy a -> Property
forall a. (Integral a, Arbitrary a, Show a) => Proxy a -> Property
integralIntegerRoundtrip Proxy a
p)
  , (String
"QuotRem is (Quot, Rem)", Proxy a -> Property
forall a. (Integral a, Arbitrary a, Show a) => Proxy a -> Property
integralQuotRem Proxy a
p)
  , (String
"DivMod is (Div, Mod)", Proxy a -> Property
forall a. (Integral a, Arbitrary a, Show a) => Proxy a -> Property
integralDivMod Proxy a
p)
  ]

integralQuotientRemainder :: forall a. (Integral a, Arbitrary a, Show a) => Proxy a -> Property
integralQuotientRemainder :: Proxy a -> Property
integralQuotientRemainder Proxy a
_ = 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
False (\(a
_,a
y) -> a
y a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
0)
  (\(a
x :: a, a
y) -> [String
"x = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
x, String
"y = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
y])
  String
"(quot x y) * y + (rem x y)"
  (\(a
x,a
y) -> (a -> a -> a
forall a. Integral a => a -> a -> a
quot a
x a
y) a -> a -> a
forall a. Num a => a -> a -> a
* a
y a -> a -> a
forall a. Num a => a -> a -> a
+ (a -> a -> a
forall a. Integral a => a -> a -> a
rem a
x a
y))
  String
"x"
  (\(a
x,a
_) -> a
x)

integralDivisionModulus :: forall a. (Integral a, Arbitrary a, Show a) => Proxy a -> Property
integralDivisionModulus :: Proxy a -> Property
integralDivisionModulus Proxy a
_ = 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
False (\(a
_,a
y) -> a
y a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
0)
  (\(a
x :: a, a
y) -> [String
"x = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
x, String
"y = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
y])
  String
"(div x y) * y + (mod x y)"
  (\(a
x,a
y) -> (a -> a -> a
forall a. Integral a => a -> a -> a
div a
x a
y) a -> a -> a
forall a. Num a => a -> a -> a
* a
y a -> a -> a
forall a. Num a => a -> a -> a
+ (a -> a -> a
forall a. Integral a => a -> a -> a
mod a
x a
y))
  String
"x"
  (\(a
x,a
_) -> a
x)

integralIntegerRoundtrip :: forall a. (Integral a, Arbitrary a, Show a) => Proxy a -> Property
integralIntegerRoundtrip :: Proxy a -> Property
integralIntegerRoundtrip Proxy a
_ = 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
x :: a) -> [String
"x = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
x])
  String
"fromInteger (toInteger x)"
  (\a
x -> Integer -> a
forall a. Num a => Integer -> a
fromInteger (a -> Integer
forall a. Integral a => a -> Integer
toInteger a
x))
  String
"x"
  (\a
x -> a
x)

integralQuotRem :: forall a. (Integral a, Arbitrary a, Show a) => Proxy a -> Property
integralQuotRem :: Proxy a -> Property
integralQuotRem Proxy a
_ = Bool
-> ((a, a) -> Bool)
-> ((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
False (\(a
_,a
y) -> a
y a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
0)
  (\(a
x :: a, a
y) -> [String
"x = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
x, String
"y = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
y])
  String
"quotRem x y"
  (\(a
x,a
y) -> a -> a -> (a, a)
forall a. Integral a => a -> a -> (a, a)
quotRem a
x a
y)
  String
"(quot x y, rem x y)"
  (\(a
x,a
y) -> (a -> a -> a
forall a. Integral a => a -> a -> a
quot a
x a
y, a -> a -> a
forall a. Integral a => a -> a -> a
rem a
x a
y))

integralDivMod :: forall a. (Integral a, Arbitrary a, Show a) => Proxy a -> Property
integralDivMod :: Proxy a -> Property
integralDivMod Proxy a
_ = Bool
-> ((a, a) -> Bool)
-> ((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
False (\(a
_,a
y) -> a
y a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
0)
  (\(a
x :: a, a
y) -> [String
"x = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
x, String
"y = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
y])
  String
"divMod x y"
  (\(a
x,a
y) -> a -> a -> (a, a)
forall a. Integral a => a -> a -> (a, a)
divMod a
x a
y)
  String
"(div x y, mod x y)"
  (\(a
x,a
y) -> (a -> a -> a
forall a. Integral a => a -> a -> a
div a
x a
y, a -> a -> a
forall a. Integral a => a -> a -> a
mod a
x a
y))