hedgehog-classes-0.1.0.0: src/Hedgehog/Classes/Generic.hs
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE QuantifiedConstraints #-}
module Hedgehog.Classes.Generic (genericLaws) where
import Hedgehog
import Hedgehog.Classes.Common
import GHC.Generics (Generic(..))
-- | Tests the following 'Generic' laws:
--
-- [__From-To Inverse__]: @'from' '.' 'to'@ ≡ @'id'@
-- [__To-From Inverse__]: @'to' '.' 'from'@ ≡ @'id'@
genericLaws ::
( Generic a, Eq a, Show a
, Eq (Rep a x), Show (Rep a x)
)
=> Gen a
-> Gen (Rep a x)
-> Laws
genericLaws gena genr = Laws "Generic"
[ ("From-To inverse", fromToInverse gena genr)
, ("To-From inverse", toFromInverse gena genr)
]
fromToInverse :: forall a x.
( Generic a
, Eq (Rep a x)
, Show (Rep a x)
) => Gen a -> Gen (Rep a x) -> Property
fromToInverse _gena genr = property $ do
r <- forAll genr
let lhs = r
let rhs = from (to r :: a)
let ctx = contextualise $ LawContext
{ lawContextLawName = "From-To inverse", lawContextTcName = "Generic"
, lawContextLawBody = "from . to" `congruency` "id"
, lawContextTcProp =
let showR = show r
in lawWhere
[ "from . to $ r" `congruency` "id r, where"
, "r = " ++ showR
]
, lawContextReduced = reduced lhs rhs
}
heqCtx lhs rhs ctx
toFromInverse :: forall a x.
( Generic a
, Eq a
, Show a
) => Gen a -> Gen (Rep a x) -> Property
toFromInverse gena _genr = property $ do
v <- forAll gena
let lhs = to (from v)
let rhs = v
let ctx = contextualise $ LawContext
{ lawContextLawName = "To-From inverse", lawContextTcName = "Generic"
, lawContextLawBody = "to . from" `congruency` "id"
, lawContextTcProp =
let showV = show v
in lawWhere
[ "to . from $ v" `congruency` "id v, where"
, "v = " ++ showV
]
, lawContextReduced = reduced lhs rhs
}
heqCtx lhs rhs ctx
{-
type Generic1Prop f =
( Generic1 f
, forall x. Eq x => Eq (f x)
, forall x. Show x => Show (f x)
, forall x. Eq x => Eq (Rep1 f x)
, forall x. Show x => Show (Rep1 f x)
) => (forall x. Gen x -> Gen (f x))
-> (forall x. Gen x -> Gen (Rep1 f x))
-> Property
fromToInverse1 :: forall f. Generic1Prop f
fromToInverse1 _genf genr = property $ do
r <- forAll $ genr genSmallInteger
r === (from1 (to1 r :: f Integer))
toFromInverse1 :: forall f. Generic1Prop f
toFromInverse1 genf _genr = property $ do
v <- forAll $ genf genSmallInteger
v === (to1 . from1 $ v)
-}
{-
generic1Laws ::
( Generic1 f
, forall x. Eq x => Eq (f x)
, forall x. Show x => Show (f x)
, forall x. Eq x => Eq (Rep1 f x)
, forall x. Show x => Show (Rep1 f x)
) => (forall x. Gen x -> Gen (f x))
-> (forall x. Gen x -> Gen (Rep1 f x))
-> Laws
generic1Laws genf genr = Laws "Generic1"
[ ("From1-To1 inverse", fromToInverse1 genf genr)
, ("To1-From1 inverse", toFromInverse1 genf genr)
]
-}