Functor

A Functor is a context/container you can map over without changing its shape.

class Functor f where
  fmap :: (a -> b) -> f a -> f b
  -- (<$>) = fmap  (infix);  (<$) replaces values

-- Laws:
--   fmap id == id
--   fmap (g . h) == fmap g . fmap h

fmap (+ 1) [1, 2, 3]             -- [2,3,4]
fmap (+ 1) (Just 5)              -- Just 6
fmap (+ 1) Nothing               -- Nothing
fmap (+ 1) (Right 5 :: Either String Int)   -- Right 6
fmap (+ 1) (Left "err")          -- Left "err"
fmap length (Just "hello")       -- Just 5
(+ 1) <$> (3, 4)                 -- (3,5): maps over the second component
fmap (* 2) (+ 10) 1              -- 22: functions are Functors (composition)
length <$> getLine               -- IO is a Functor
"x" <$ Just 1                    -- Just "x"
void (Just 3)                    -- Just ()  (Data.Functor)

-- Instance for our Tree
data Tree a = Leaf | Node (Tree a) a (Tree a) deriving Show

instance Functor Tree where
  fmap _ Leaf = Leaf
  fmap f (Node l x r) = Node (fmap f l) (f x) (fmap f r)

-- Or derive it: {-# LANGUAGE DeriveFunctor #-} (in GHC2021)  data Tree a = ... deriving (Functor)