module Spec where -- a) {- -- These are already in Control.Monad.Instances instance Functor (Either e) where fmap = fmapE instance Functor ((,) e) where fmap = fmapP instance Functor ((->) e) where fmap = fmapF -} fmapE :: (a->b) -> (Either e a) -> (Either e b) fmapE f (Left e) = Left e fmapE f (Right a) = Right (f a) fmapP :: (a->b) -> (e, a) -> (e, b) fmapP f (e, a) = (e, f a) fmapF :: (a->b) -> (e->a) -> (e->b) fmapF f g = f . g {- -- Monads? (Either e) is the Error monad ((,) e) is the Writer monad if e is a monoid (less well-known) ((->) e) is the Reader monad -} ---------------------------------------------------------------- -- b) -- -------------- -- Functor laws (here as QuickCheck properties) fmapId :: (Functor f, Eq (f a)) => f a -> Bool fmapId = fmap id === id fmapComp f g = (fmap f) . (fmap g) === fmap (f . g) infix 4 === (===) :: Eq a => (t -> a) -> (t -> a) -> t -> Bool (f === g) x = f x == g x -- Prove the Functor laws -- fmapId fmapId_E x = [ fmapE id x , case x of Left e -> Left e Right a -> Right (id a) , case x of Left e -> Left e Right a -> Right a , x ] fmapId_P (e, a) = [ fmapP id (e, a) , (e, id a) , (e, a) ] fmapId_F f = [ fmapF id f , id . f , \x -> id (f x) , \x -> f x ] ---------------- -- fmapComp fmapComp_E f g (Left e) = [ ((fmapE f) . (fmapE g)) (Left e) , fmapE f (fmapE g (Left e)) , fmapE f (Left e) , Left e , fmapE (f . g) (Left e) ] fmapComp_E f g (Right a) = [ ((fmapE f) . (fmapE g)) (Right a) , fmapE f (fmapE g (Right a)) , fmapE f (Right (g a)) , Right (f (g a)) , Right ((f . g) a) , fmapE (f . g) (Right a) ] fmapComp_P f g (e, a) = [ ((fmapP f) . (fmapP g)) (e, a) , fmapP f (fmapP g (e, a)) , fmapP f (e, g a) , (e, f (g a)) , (e, (f . g) a) , fmapP (f . g) (e, a) ] fmapComp_F f g h = [ ((fmapF f) . (fmapF g)) h , fmapF f (fmapF g h) , fmapF f (g . h) , f . (g . h) , (f . g) . h , fmapF (f . g) h ] ---------------- -- Some testing code (just started) - not part of the exam question. allEq :: Eq a => [a] -> Bool allEq [] = True allEq (x:xs) = all (x==) xs p_E f g x = allEq (fmapComp_E f g x)