hedgehog-classes-0.1.0.0: src/Hedgehog/Classes/Arrow.hs
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE QuantifiedConstraints #-}
module Hedgehog.Classes.Arrow (arrowLaws) where
import Hedgehog
import Hedgehog.Classes.Common
import Control.Arrow(Arrow(..), (>>>))
import Control.Category(Category(..))
import Prelude hiding (id, (.))
import qualified Prelude
-- | Tests the following 'Arrow' laws:
--
-- [__Arr Identity__]: @'arr' 'id'@ ≡ @'id'@
-- [__Arr Composition__]: @'arr' (f '>>>' g)@ ≡ @'arr' f '>>>' 'arr' g@
-- [__Arr-First inverse__]: @'first' ('arr' f)@ ≡ @'arr' ('first' f)@
-- [__First Composition__]: @'first' (f '>>>' g)@ ≡ @'first' f '>>>' 'first' g@
-- [__Arrow Law 5__]: @'first' f '>>>' 'arr' 'fst'@ ≡ @'arr' 'fst' '>>>' f@
-- [__Arrow Law 6__]: @'first' f '>>>' 'arr' ('id' '***' g)@ ≡ @'arr' ('id' '***' g) '>>>' 'first' f@
-- [__Arrow Law 7__]: @'first' ('first' f) '>>>' 'arr' assoc@ ≡ @'arr' assoc '>>>' 'first' f, where assoc ((a,b),c) = (a,(b,c))@
arrowLaws :: forall f.
( Arrow 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
arrowLaws gen = Laws "Arrow"
[ ("Arr Identity", arrowLaw1 gen)
, ("Arr Composition", arrowLaw2 gen)
, ("Arr . First == First . Arr", arrowLaw3 gen)
, ("First Composition", arrowLaw4 gen)
, ("Arrow Law 5", arrowLaw5 gen)
, ("Arrow Law 6", arrowLaw6 gen)
, ("Arrow Law 7", arrowLaw7 gen)
]
type ArrowProp f =
( Arrow 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
arrowLaw1 :: forall f. ArrowProp f
arrowLaw1 _ = property $ do
arr Prelude.id `heq2` (id :: f Integer Integer)
arrowLaw2 :: forall f. ArrowProp f
arrowLaw2 _ = property $ do
f' <- forAll genQuadraticEquation
g' <- forAll genQuadraticEquation
let f = runQuadraticEquation f'
g = runQuadraticEquation g'
(arr (f >>> g) :: f Integer Integer) `heq2` (arr f >>> arr g)
arrowLaw3 :: forall f. ArrowProp f
arrowLaw3 _ = property $ do
f' <- forAll genQuadraticEquation
let f = runQuadraticEquation f'
let x = first (arr f) :: f (Integer, Integer) (Integer, Integer)
let y = arr (first f) :: f (Integer, Integer) (Integer, Integer)
x `heq2` y
arrowLaw4 :: forall f. ArrowProp f
arrowLaw4 fgen = property $ do
f <- forAll $ fgen genSmallInteger genSmallInteger
g <- forAll $ fgen genSmallInteger genSmallInteger
let x = first (f >>> g) :: f (Integer, Integer) (Integer, Integer)
let y = first f >>> first g :: f (Integer, Integer) (Integer, Integer)
x `heq2` y
arrowLaw5 :: forall f. ArrowProp f
arrowLaw5 fgen = property $ do
f <- forAll $ fgen genSmallInteger genSmallInteger
let x = first f >>> arr fst :: f (Integer, Integer) Integer
let y = arr fst >>> f :: f (Integer, Integer) Integer
x `heq2` y
arrowLaw6 :: forall f. ArrowProp f
arrowLaw6 fgen = property $ do
f <- forAll $ fgen genSmallInteger genSmallInteger
g' <- forAll genQuadraticEquation
let g = runQuadraticEquation g'
let x = ((first f) >>> (arr (Prelude.id *** g))) :: f (Integer, Integer) (Integer, Integer)
let y = arr (id *** g) >>> first f :: f (Integer, Integer) (Integer, Integer)
x `heq2` y
arrowLaw7 :: forall f. ArrowProp f
arrowLaw7 fgen = property $ do
let assoc ((a,b),c) = (a,(b,c))
f <- forAll $ fgen genSmallInteger genSmallInteger
let x = first (first f) >>> arr assoc :: f ((Integer, Integer), Integer) (Integer, (Integer, Integer))
let y = arr assoc >>> first f :: f ((Integer, Integer), Integer) (Integer, (Integer, Integer))
x `heq2` y