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)