Functors
A functor most satisfy two properties:
- When
idis applied to , the result must be . - 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 >>= \_ -> kA 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