{-# 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