Haskell Functor laws for Maybe
data Mabye a = Nothing | Just a
class Functor f where
fmap::(a -> b) -> f a -> f b
-- fmap f box -> box
instance of Functor need to satisfy two laws.
instance Functor Maybe where
fmap f Nothing = Nothing -- f is function, it is NOT a functor
fmap f (Just a) = Just (f a)
-- Show Functor Maybe satisfies the two laws:
fmap id = id
fmap (f . g) = (fmap f) . (fmap g)
Proof:
fmap id Nothing = Nothing -- by defintion
id Nothing = Nothing -- by definition of identity function
=> fmap id Nothing = id Nothing (1)
fmap id (Just a) = Just a -- by defintion of fmap
id (Just a) = Just a -- by defintion of identity function
fmap id (Just a) = id (Just a) = Just a
=> fmap id (Just a) = id (Just a) (2)
(1)(2) => fmap id = id [1]
fmap (f . g) (Just a) = Just ((f . g) a) -- by defintion of fmap
= Just (f(g a)) -- by function composition
((fmap f) . (fmap g)) (Just a) = (fmap f) ( fmap g (Just a))
= (fmap f) (Just (g a)) -- defintion of fmap
= Just f(g a) -- defintion of fmap
=> fmap (f . g) (Just a) = (fmap f) . (fmap g) (Just a) [2]
[1],[2] => Maybe is a Functor
Prove MyMaybe is NOT a Functor
data MyMaybe a = MyNothing | MyJust Int a deriving (Show)
instance Functor MyMaybe where
fmap f MyNothing = MyNothing
fmap f (MyJust c a) = (MyJust (c + 1) (f a)
print $ MyNothing -- MyNothing
print $ fmap (+1) (MyJust 0 2) -- MyJust 1 3
print $ fmap id (MyJust 0 2) -- MyJust 1 2
print $ id (MyJust 0 2) -- MyJust 0 2
-- we have
fmap id (MyJust 0 2) /= id (MyJust 0 2)
=> fmap id /= id
-- Functor has to satisfy two laws:
fmap id = id [1]
fmap (f . g) = (fmap f) . (fmap g) [2]
=> MyMaybe breaks the first law [1]
=> MyMaybe is NOT a Functor