{-# LANGUAGE ScopedTypeVariables #-}

{-# OPTIONS_GHC -Wall #-}

module Test.QuickCheck.Classes.Ix
  ( ixLaws
  ) where

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

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

-- | Tests the various 'Ix' properties:
--
--   @'inRange' (l,u) i '==' 'elem' i ('range' (l,u))@
--
--   @'range' (l,u) '!!' 'index' (l,u) i '==' i@, when @'inRange' (l,u) i@
--
--   @'map' ('index' (l,u)) ('range' (l,u)) '==' [0 .. 'rangeSize' (l,u) - 1]@
--   
--   @'rangeSize' (l,u) '==' 'length' ('range' (l,u))@
ixLaws :: (Ix a, Arbitrary a, Show a) => Proxy a -> Laws
ixLaws :: Proxy a -> Laws
ixLaws Proxy a
p = String -> [(String, Property)] -> Laws
Laws String
"Ix"
  [ (String
"InRange", Proxy a -> Property
forall a. (Show a, Ix a, Arbitrary a) => Proxy a -> Property
ixInRange Proxy a
p)
  , (String
"RangeIndex", Proxy a -> Property
forall a. (Show a, Ix a, Arbitrary a) => Proxy a -> Property
ixRangeIndex Proxy a
p)
  , (String
"MapIndexRange", Proxy a -> Property
forall a. (Show a, Ix a, Arbitrary a) => Proxy a -> Property
ixMapIndexRange Proxy a
p)
  , (String
"RangeSize", Proxy a -> Property
forall a. (Show a, Ix a, Arbitrary a) => Proxy a -> Property
ixRangeSize Proxy a
p)
  ]

ixInRange :: forall a. (Show a, Ix a, Arbitrary a) => Proxy a -> Property
ixInRange :: Proxy a -> Property
ixInRange Proxy a
_ = (a -> a -> a -> Property) -> Property
forall prop. Testable prop => prop -> Property
property ((a -> a -> a -> Property) -> Property)
-> (a -> a -> a -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \(a
l :: a) (a
u :: a) (a
i :: a) -> (a
l a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
u) Bool -> Bool -> Property
forall prop. Testable prop => Bool -> prop -> Property
==> do
  (a, a) -> a -> Bool
forall a. Ix a => (a, a) -> a -> Bool
inRange (a
l,a
u) a
i Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
== a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
elem a
i ((a, a) -> [a]
forall a. Ix a => (a, a) -> [a]
range (a
l,a
u))

ixRangeIndex :: forall a. (Show a, Ix a, Arbitrary a) => Proxy a -> Property
ixRangeIndex :: Proxy a -> Property
ixRangeIndex Proxy a
_ = (a -> a -> a -> Property) -> Property
forall prop. Testable prop => prop -> Property
property ((a -> a -> a -> Property) -> Property)
-> (a -> a -> a -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \(a
l :: a) (a
u :: a) (a
i :: a) -> ((a
l a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
u) Bool -> Bool -> Bool
&& (a
i a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
l Bool -> Bool -> Bool
&& a
i a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
u)) Bool -> Bool -> Property
forall prop. Testable prop => Bool -> prop -> Property
==> do
  (a, a) -> [a]
forall a. Ix a => (a, a) -> [a]
range (a
l,a
u) [a] -> Int -> a
forall a. [a] -> Int -> a
!! (a, a) -> a -> Int
forall a. Ix a => (a, a) -> a -> Int
index (a
l,a
u) a
i a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
i

ixMapIndexRange :: forall a. (Show a, Ix a, Arbitrary a) => Proxy a -> Property
ixMapIndexRange :: Proxy a -> Property
ixMapIndexRange Proxy a
_ = (a -> a -> Property) -> Property
forall prop. Testable prop => prop -> Property
property ((a -> a -> Property) -> Property)
-> (a -> a -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \(a
l :: a) (a
u :: a) -> (a
l a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
u) Bool -> Bool -> Property
forall prop. Testable prop => Bool -> prop -> Property
==> do
  (a -> Int) -> [a] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map ((a, a) -> a -> Int
forall a. Ix a => (a, a) -> a -> Int
index (a
l,a
u)) ((a, a) -> [a]
forall a. Ix a => (a, a) -> [a]
range (a
l,a
u)) [Int] -> [Int] -> Bool
forall a. Eq a => a -> a -> Bool
== [Int
0 .. (a, a) -> Int
forall a. Ix a => (a, a) -> Int
rangeSize (a
l,a
u) Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1]

ixRangeSize :: forall a. (Show a, Ix a, Arbitrary a) => Proxy a -> Property
ixRangeSize :: Proxy a -> Property
ixRangeSize Proxy a
_ = (a -> a -> Property) -> Property
forall prop. Testable prop => prop -> Property
property ((a -> a -> Property) -> Property)
-> (a -> a -> Property) -> Property
forall a b. (a -> b) -> a -> b
$ \(a
l :: a) (a
u :: a) -> (a
l a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
u) Bool -> Bool -> Property
forall prop. Testable prop => Bool -> prop -> Property
==> do
  (a, a) -> Int
forall a. Ix a => (a, a) -> Int
rangeSize (a
l,a
u) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ((a, a) -> [a]
forall a. Ix a => (a, a) -> [a]
range (a
l,a
u))