{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE QuantifiedConstraints #-}
module Hedgehog.Classes.Bifunctor (bifunctorLaws) where
import Hedgehog
import Hedgehog.Classes.Common
import Data.Bifunctor (Bifunctor(..))
bifunctorLaws :: forall f.
( Bifunctor f
, forall x y. (Eq x, Eq y) => Eq (f x y)
, forall x y. (Show x, Show y) => Show (f x y)
) => (forall x y. Gen x -> Gen y -> Gen (f x y)) -> Laws
bifunctorLaws gen = Laws "Bifunctor"
[ ("Identity", bifunctorIdentity gen)
, ("First Identity", bifunctorFirstIdentity gen)
, ("Second Identity", bifunctorSecondIdentity gen)
, ("Composition", bifunctorComposition gen)
]
type BifunctorProp f =
( Bifunctor f
, forall x y. (Eq x, Eq y) => Eq (f x y)
, forall x y. (Show x, Show y) => Show (f x y)
) => (forall x y. Gen x -> Gen y -> Gen (f x y)) -> Property
bifunctorIdentity :: forall f. BifunctorProp f
bifunctorIdentity fgen = property $ do
x <- forAll $ fgen genSmallInteger genSmallInteger
let lhs = bimap id id x
let rhs = x
let ctx = contextualise $ LawContext
{ lawContextLawName = "Identity", lawContextLawBody = "bimap id id" `congruency` "id"
, lawContextTcName = "Bifunctor", lawContextTcProp =
let showX = show x;
in lawWhere
[ "bimap id id x" `congruency` "x, where"
, "x = " ++ showX
]
, lawContextReduced = reduced lhs rhs
}
heqCtx2 lhs rhs ctx
bifunctorFirstIdentity :: forall f. BifunctorProp f
bifunctorFirstIdentity fgen = property $ do
x <- forAll $ fgen genSmallInteger genSmallInteger
let lhs = first id x
let rhs = x
let ctx = contextualise $ LawContext
{ lawContextLawName = "First Identity", lawContextLawBody = "first id" `congruency` "id"
, lawContextTcName = "Bifunctor", lawContextTcProp =
let showX = show x;
in lawWhere
[ "first id x" `congruency` "x, where"
, "x = " ++ showX
]
, lawContextReduced = reduced lhs rhs
}
heqCtx2 lhs rhs ctx
bifunctorSecondIdentity :: forall f. BifunctorProp f
bifunctorSecondIdentity fgen = property $ do
x <- forAll $ fgen genSmallInteger genSmallInteger
let lhs = second id x
let rhs = x
let ctx = contextualise $ LawContext
{ lawContextLawName = "Second Identity", lawContextLawBody = "second id" `congruency` "id"
, lawContextTcName = "Bifunctor", lawContextTcProp =
let showX = show x;
in lawWhere
[ "second id x" `congruency` "x, where"
, "x = " ++ showX
]
, lawContextReduced = reduced lhs rhs
}
heqCtx2 lhs rhs ctx
bifunctorComposition :: forall f. BifunctorProp f
bifunctorComposition fgen = property $ do
z <- forAll $ fgen genSmallInteger genSmallInteger
let lhs = bimap id id z
let rhs = (first id . second id) z
let ctx = contextualise $ LawContext
{ lawContextLawName = "Composition", lawContextLawBody = "bimap id id" `congruency` "first id . second id"
, lawContextTcName = "Bifunctor", lawContextTcProp =
let showX = show z;
in lawWhere
[ "bimap id id x" `congruency` "first id . second id $ x, where"
, "x = " ++ showX
]
, lawContextReduced = reduced lhs rhs
}
heqCtx2 lhs rhs ctx