content: 
  module ReplaceExperiment where
  
  import Data.Functor ((<$>))
  
  replaceWithP :: b -> Char
  replaceWithP = const 'p'
  
  lms :: [Maybe [Char]]
  lms = [Just "Ave", Nothing, Just "woohoo"]
  
  replaceWithP' :: [Maybe [Char]] -> Char
  replaceWithP' = replaceWithP
  
  liftedReplace :: Functor f => f a -> f Char
  liftedReplace = fmap replaceWithP
  
  liftedReplace' :: [Maybe [Char]] -> [Char]
  liftedReplace' = liftedReplace
  
  twiceLifted :: (Functor f1, Functor f) =>
                 f (f1 a) -> f (f1 Char)
  twiceLifted = (fmap . fmap) replaceWithP
  
  twiceLifted' :: [Maybe [Char]] -> [Maybe Char]
  twiceLifted' = twiceLifted
  
  thriceLifted :: (Functor f2, Functor f1, Functor f) =>
                  f (f1 (f2 a)) -> f (f1 (f2 Char))
  thriceLifted = (fmap . fmap . fmap) replaceWithP
  
  thriceLifted' :: [Maybe [Char]] -> [Maybe [Char]]
  thriceLifted' = thriceLifted
  
  main :: IO ()
  main = do
    putStr "replaceWithP' lms: "
    print (replaceWithP' lms)
    putStr "liftedReplace lms: "
    print (liftedReplace lms)
    putStr "liftedReplace' lms: "
    print (liftedReplace' lms)
    putStr "twiceLifted lms: "
    print (twiceLifted lms)
    putStr "twiceLifted' lms: "
    print (twiceLifted' lms)
    putStr "thriceLifted lms: "
    print (thriceLifted lms)
    putStr "thriceLifted' lms: "
    print (thriceLifted' lms)
  
  -- Lifting
  
  a = (+1) <$> read "[1]" :: [Int]
  
  b = (fmap . fmap) (++ "lol") (Just ["Hi,", "Hello"])
  
  c = fmap (* 2) (\x -> x - 2)
  
  d = fmap ((return '1' ++) . show) (\x -> [x, 1..3])
  
  e :: IO Integer
  e = let ioi = readIO "1" :: IO Integer
          changed = fmap (read . ("123"++) . show) ioi
      in fmap (* 3) changed
  
  -- 16.8
  
  data Two a b = Two a b deriving (Eq, Show)
  
  data Or a b = First a | Second b deriving (Eq, Show)
  
  instance Functor (Two a) where
    fmap f (Two a b) = Two a (f b)
  
  instance Functor (Or a) where
    fmap _ (First a) = First a
    fmap f (Second b) = Second (f b)
  
  