{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE ScopedTypeVariables #-} module Test.Validity.Functions.Idempotence ( -- ** Standard tests involving validity idempotentOnGen , idempotentOnValid , idempotent , idempotentOnArbitrary ) where import Data.GenValidity import Test.Hspec import Test.QuickCheck idempotentOnGen :: (Show a, Eq a) => (a -> a) -> Gen a -> Property idempotentOnGen f gen = forAll gen $ \a -> f (f a) `shouldBe` f a idempotentOnValid :: (Show a, Eq a, GenValidity a) => (a -> a) -> Property idempotentOnValid func = idempotentOnGen func genValid idempotent :: (Show a, Eq a, GenValidity a) => (a -> a) -> Property idempotent func = idempotentOnGen func genUnchecked -- | -- -- 'id' is idempotent for any type: -- -- prop> idempotentOnArbitrary (id :: Int -> Int) -- -- 'const', given any input, is idempotent for any type as well: -- -- prop> \int -> idempotentOnArbitrary (const int :: Int -> Int) idempotentOnArbitrary :: (Show a, Eq a, Arbitrary a) => (a -> a) -> Property idempotentOnArbitrary func = idempotentOnGen func arbitrary