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 >>= \-> e2