Functors

A functor 𝑓 most satisfy two properties:

  1. When id is applied to 𝑓, the result must be 𝑓.
  2. When 𝑔.ℎ is applied to 𝑓, the result must be equivalent to first applying ℎ, then applying 𝑔.

Our Parser is a functor because we just apply the function to the current AST of our parser. Basically, a functor is anything to which a function can be nicely applied (that is, it follows the rules outlined above).

x <$ f sets the contents of 𝑓 to the constant value 𝑥.

Applicatives

An applicative type is a type which can be applied to itself. An example is a list:

> [(*2), (+3)] <*> [1, 2, 3]
[2, 4, 6, 4, 5, 6]

Likewise, our parsers can also be applied to themselves. If 𝑎 and 𝑏 are parsers, 𝑎.𝑏 simply corresponds to chaining the two parsers together.

The pure attribute of an applicative is just a way to wrap some function: pure 𝑓 will wrap the function 𝑓 into our desired type.

The <* and *> operators can chain applicatives together.

Monads

infixl 1  >>, >>=  
class  Monad m  where  
    (>>=)            :: m a -> (a -> m b) -> m b  
    (>>)             :: m a -> m b -> m b  
    return           :: a -> m a  
    fail             :: String -> m a  
  
    m >> k           =  m >>= \_ -> k

A monad is essentially a type that wraps a value and allows this value to be transformed.

(>>): transforms a monad without reading its current value

do blocks

do e1 ; e2      =        e1 >> e2  
do p <- e1; e2  =        e1 >>= \p -> e2