class Eq a where
    (==) :: a -> a -> Bool
    (/=) :: a -> a -> Bool
    x == y = not (x /= y)
    x /= y = not (x == y)
  class (Eq a) => Num a where
    ...
  data TrafficLight = Red | Yellow | Green
instance Eq TrafficLight where
    Red == Red = True
    Green == Green = True
    Yellow == Yellow = True
    _ == _ = False
  What if you have a type constructor instead of a type?
instance (Eq m) => Eq (Maybe m) where
    Just x == Just y = x == y
    Nothing == Nothing = True
    _ == _ = False
  
Let’s practice interpreting function types
a -> b
  (a -> b) -> [a] -> [b]
  (b -> c) -> (a -> b) -> a -> c
  class Functor f where
    fmap :: (a -> b) -> f a -> f b
  instance Functor [] where
    fmap = map
  Why is the declaration not this?
instance Functor [a] where
    fmap = map
    f is a type constructor
      Can you write
      fmap
      for Maybe?
    
instance Functor Maybe where
    fmap f (Just x) = Just (f x)
    fmap f Nothing = Nothing
    
      How about
      Functor Tree
      ?
    
instance Functor Tree where
    fmap f EmptyTree = EmptyTree
    fmap f (Node v left right) = Node (f v) (fmap f left) (fmap f right)
  instance Functor IO where
    fmap f action = do
        result <- action
        return (f result)
  
      What is the type constructor
      (->) r
      ?
    
      Well
      ((->) r) a
      is equivalent to
      (->) r a
      is equivalent to
      r -> a
    
It’s just a type constructor creating a function type
      How do we implement
      fmap
      over function type constructors?
    
instance Functor ((->) r) where
    fmap = ...
  
      (a -> b) -> (r -> a) -> (r -> b)
    
That’s our type for function composition!
instance Functor ((->) r) where
    fmap = (.)
  fmap id = id
  fmap (f . g) = fmap f . fmap g
  fmap
        ?
      map
      fmap
        lets us operate on on Functor
      It turns out we can do something like this
ghci> (+) <$> Just 4 <*> Just 5
Just 9
ghci> (+) <$> Nothing <*> Just 5
Nothing
  But we need some machinery first
pure
      “wraps” the argument in the functor
    <*>
      is like fmap but the mapping function is inside the functor
    class (Functor f) => Applicative f where
    pure :: a -> f a
    (<*>) :: f (a -> b) -> f a -> f b
instance Applicative Maybe where
    pure = Just
    Nothing <*> _ = Nothing
    (Just f) <*> something = fmap f something
  ghci> Just (+3) <*> Just 9
Just 12
ghci> pure (+3) <*> Nothing
Nothing
ghci> Nothing <*> Just 5
Nothing
ghci> pure (+) <*> Just 5 <*> Just 7
Just 12
  pure f <*> arg
      doing?
    fmap f arg
    <$>
      is a sugary infix fmap operator
    instance Applicative [] where
    pure x = [x]
    fs <*> xs = [f x | f <- fs, x <- xs]
    ghci> [(+), (*)] <*> [1, 2] <*> [3, 4]
[4,5,5,6,3,4,6,8]
  instance Applicative IO where
    pure = return
    a <*> b = do
        f <- a
        x <- b
        return (f x)
    ghci> (++) <*> getLine <*> getLine
Hello
 World!
"Hello World!"
  A monad in X is just a monoid in the category of endofunctors of X, with product × replaced by composition of endofunctors and unit set by the identity endofunctor.
Let’s start somewhere else.
class (Applicative m) => Monad m where
    return :: a -> m a
    (>>=) :: m a -> (a -> m b) -> m b
    (>>) :: m a -> m b -> m b
    x >> y = x >>= \_ -> y
  return
    return
        is exactly like
        pure
      >>=
    instance Monad Maybe where
    return x = Just x
    Nothing >>= f = Nothing
    Just x >>= f  = f x
  See Learn You a Haskell for the full example
return (0,0) >>= landLeft 1 >> landRight 4 >>= landLeft 2 >>= landLeft 1
    routine = case landLeft 1 (0,0) of
    Nothing -> Nothing
    Just pole1 -> case landRight 4 pole1 of
        Nothing -> Nothing
        Just pole2 -> case landLeft 2 pole2 of
            Nothing -> Nothing
            Just pole3 -> landLeft 1 pole3
  Remember our greet program?
greet :: IO ()
greet = do
    putStr "What is your first name? "
    firstName <- getLine
    putStr "What is your last name? "
    lastName <- getLine
    putStrLn $ "Hi " ++ firstName ++ " " ++ lastName ++ "!"
    return ()
  greet :: IO ()
greet =
    putStr "What is your first name? " >>
    getLine >>= (\firstName ->
        putStr "What is your last name? " >>
        getLine >>= (\lastName ->
            putStrLn ("Hi " ++ firstName ++ " " ++ lastName ++ "!") >>
            return ()
        )
    )
  do
        is just syntactic sugar for monad operations
      routine = case landLeft 1 (0,0) of
    Nothing -> Nothing
    Just pole1 -> case landRight 4 pole1 of
        Nothing -> Nothing
        Just pole2 -> case landLeft 2 pole2 of
            Nothing -> Nothing
            Just pole3 -> landLeft 1 pole3
    routine :: Maybe (Int, Int)
routine = do
     start <- return (0,0)
     pole1 <- landLeft 1 start
     pole2 <- landRight 4 pole1
     pole3 <- landLeft 2 start
     return $ landLeft 1 pole3
  instance Monad [] where
    return x = [x]
    xs >>= f = concat (map f xs)
  ghci> [1,2] >>= \n -> ['a','b'] >>= \ch -> return (n,ch)
[(1,'a'),(1,'b'),(2,'a'),(2,'b')]
  listOfTuples :: [(Int,Char)]
listOfTuples = do
    n <- [1,2]
    ch <- ['a','b']
    return (n,ch)
  [(n,ch) | n <- [1,2], ch <- ['a','b']]