(En) Comparision of functor, applicative and monad

Posted on February 9, 2023 by lk
Tags: haskell, monoid, monad, functor, applicative

Outline

We will dicuss about the relationship between each type class (monoid, functor, applicative, and monad). You can discover more with the links to the relevant videos as bellow (English videos coming soon).

Review about type signature of ($), (<>), (<$>), (<*>), (>>=) or flip bind (=<<)

let’s say that function f has signature f :: a -> b, we have these equivalent transformations as below

f             :: a -> b
f a           :: b                  -- apply f to a
(a -> b) -> a :: b                  -- replace f with (a -> b)
($)           :: (a -> b) -> a ->b

In fact, we see lots of block of code as below

print $ show a

We see that (<>) or mappend receive 2 params which have the same type (structure), and return the result which also keep the original structure (type)

putStrLn $ "hello" <> " " <> "world!"

(\x -> x * 2) <$> [1..2]

getSum $ fold $ Sum <$> [1..5]
pure (\x -> x * 2) <*> [1..2]

getSum $ fold $ pure Sum <*> [1..5]

In real life, we see many computation cases that need to take value a out of the computation context (or take value a out of any context(structure) which denoted as m)

The sample bellow, illustrate the case that we need to take a value a out of Maybe structure, and then calling (+) function for a sum computation, and then put the result value into Maybe structure.

maybePlus :: Maybe Int -> Maybe Int -> Maybe Int
maybePlus ma mb =
  case ma of
    Nothing -> Nothing
    Just a ->
      case mb of
        Nothing -> Nothing
        Just b  -> Just (a + b)

-- helper function
andThen :: Maybe a -> (a -> Maybe b) -> Maybe b
andThen ma f =
  case ma of
    Nothing -> Nothing
    Just a  -> f a

-- using helper function to refactor
maybePlus' :: Maybe Int -> Maybe Int -> Maybe Int
maybePlus' ma mb = ma `andThen` \a -> mb `andThen` \b -> Just (a + b)

Relation between ($) (<>) <*>

($)   ::   (a -> b)   ->   a ->   b
(<>)  :: f            -> f   -> f 
(<*>) :: f (a -> b)   -> f a -> f b

We can see that (<*>) indeed is the combination of ($) and (<>)

Relation between <$> (=<<)

(<$>) :: (a -> b)  -> f a -> f b

(=<<) :: (a-> m b) -> m a -> m b

We can see that flip bind function (=<<) is the combination in order of fmap and join :: Monad m => m (m a) -> m a function. You can read more about the equivalent transformations here(english version coming soon, but i hope that you can understand the equivalent transformations)

Ref