I've come to understand functors, applicative functors, and monads as follows:
However, there is something about Applicative that conflicts with my understanding... Here is a Haskell example of a parser defined on the basis of more basic parsers using the applicative style:
(,) <$> parseName <*> parseEmail
The effects of the two parsers, parseName
and parseEmail
, are not independent, because they both consume tokens from the same input stream, e.g.
Jubobs [email protected]
parseEmail
can only consume what hasn't been consumed by parseName
. How, then, can the two computations be said to be independent?
Functors apply a function to a wrapped value: Applicatives apply a wrapped function to a wrapped value: Monads apply a function that returns a wrapped value to a wrapped value. Monads have a function >>= (pronounced "bind") to do this.
Applicative functors are the programming equivalent of lax monoidal functors with tensorial strength in category theory. Applicative functors were introduced in 2008 by Conor McBride and Ross Paterson in their paper Applicative programming with effects.
Monads are not a replacement for applicative functors Instead, every monad is an applicative functor (as well as a functor). It is considered good practice not to use >>= if all you need is <*>, or even fmap.
In functional programming, a functor is a design pattern inspired by the definition from category theory, that allows for a generic type to apply a function inside without changing the structure of the generic type. Simple examples of this are Option and collection types.
The independence here is not saying that one computation cannot detect what other computations have been run - that is, it's not supposed to be the case that parseName has no effect on parseEmail. Rather, you cannot make use of the applicative value (the name parsed by parseName) to choose what applicative computation to run next: you can only ever parse a generic email, rather than, say, parsing an email address while checking that it does not contain the parsed name.
Another way of putting it is that if you use only applicative functions, the overall "shape" of your computation is predetermined ahead of time: you will always parse a name, followed by an email address. If you used monadic functions, you could make decisions about what to parse next based on the results of previous parses, letting you change the shape of your computation as it is running.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With