3 ms·
My mental model is that applicatives are the multivariate analog of functors. To invent some terms because I don’t know the real ones, call the types `Maybe In
by 6gvONxR4sf7o 5y ago
My mental model is that applicatives are the multivariate analog of functors.
To invent some terms because I don’t know the real ones, call the types `Maybe Int`, `List Bool`, and the rest of the `m a` types “boxed,” compared to types like Int and Bool which we’ll call “unboxed.”
Functors apply single variable functions that apply purely in the unboxed domain. Take a `List Int` apply an `Int -> Float` function and you get a `List Float`. But you can’t use functors to take a `List Int` and a `List Float` to get a `List Bool` with an `Int -> Float -> Bool` function.
That’s where applicatives come in. Applicatives still operate in terms of applying functions that live in the unboxed domain. `Int -> Float` or `Int -> Float -> Bool` and that kind of thing. But if you had a `List Int` and something boxy like `Int -> List Float`, you have no way to get a `List Float` out the other end.
That’s where monads come in. These can operate on functions that don’t only live in the unboxed domain. You can take your `List Int` and your `Int -> List Float` and get a `List Float` out the other end.
As far as what you need to add for something to be a monad, I think there are cleaner answers that are logically equivalent, but what comes to mind is “flattening” (again for lack of remembering the real terms). Imagine you use the functor or applicative machinery on your boxy functions (that take in unboxed stuff and return boxed stuff). For example, using a `List Int`’s map on a `Int -> List Float`. You end up with `List (List Float)`. To build a monad’s `bind` out of that, you need another function to follow up: `List (List Float) -> List Float`. Aka, flatten that list of lists into a single list.