When I was reading about these stuff, I was not lucky enough to find such a clear high level description of what is the purpose of a monad. I got it eventually, but I wish I encountered this concise description earlier.
When I was reading about these stuff, I was not lucky enough to find such a clear high level description of what is the purpose of a monad. I got it eventually, but I wish I encountered this concise description earlier.
The essence of monads is not about what use can be made of them either, just like the essence of things that have a hook is not that you can use them to hang your coat.
Simply put, monads are data types that share a set of properties. Think of them as you would think of the atoms that are halogens, or of the animals that are mammal. In the case of monads, the property is that functions can be chained on them in a specific way, and that the result of this chaining respects some rules.
The reason it is so hard to explain or understand monads is that this property in many different ways for many different ends, and that the what and the why are often mixed in the explanation.
Isn't it just that you can define monadic interfaces for lists, as you can with (probably all) parametric data types?
Saying "the list monad" wouldn't be correct, right? Although it's pretty common to see that phrase.
You can say "the list monad" reasonably because there is only one sensible implementation of (List a -> (a -> List b) -> List b) in Haskell. You could unconditionally return an empty List b and fulfill that interface, but what would be the point of that? You can't just return a list of all the things the function call resulted in because that would be a List of a List of b, which is not the same as a List of b. You can't sort them in Haskell because you don't have any form of comparability available in that interface specification. etc.
Technically in other languages this may be less true as due to having fewer restrictions (for example, you may in a language that defines ordering on all values, and thus you could sort the result regardless of the types involved) you can do more things, but there's still really only one sensible and unsurprising implementation.
While this may be true, I think the main reason you hear "the list monad" in Haskell is that Haskell doesn't support multiple instances of a type class (such as Monad) for a single data type (such as List/[]); and the Prelude already includes such an instance, which then becomes the List Monad.
This limitation is perhaps not often relevant for Monads, but it is sometimes relevant for other Algebraic structures. For example, there are two very common Monoids on Number: (Number, +, 0) and (Number, *, 1).
Technically, if you were the pervert kind of developer, you could revert the list.
It would therefore be correct (but slightly pedantic) to talk about "the list monad".
> as you can with (probably all) parametric data types?
Actually, you can't. For instance, if you define a predicate type:
`data Predicate a = Predicate (a -> Bool)`
It is not a monad, it's not even a functor. (If you're interested in what it is you can look into contravariant functors).
The understanding of the monad as a wrapper with a combinator equivalent to function composition is simply correct.
A list is absolutely a monad.
You actually can't implement Monad for most contravariant functors.
Monad is an interface, just like List. You don't implement a list using a monad, anymore than you implement a list using a set or a tree.
I wrote about this extensively in http://www.jerf.org/iri/post/2958, "Functors and Monads For People Who Have Read Too Many 'Tutorials'". If original post is from 2008, then it is the sort of "too many 'tutorials'" that you may have read about them.
The essence of the understanding that Monads act as a wrapper and define lifting and composition of wrapped types is correct in essence and that's the meat of the understanding. Define it a bit more rigorously and it's literally mathematically équivalent to saying "monoid over the category of endofunctors".
You can use it with the list monad for example and not IO at all.
And yes, that goes with the list monad too when using do notation. It's syntactically and in practice almost as if you were mutating a new list and then returning it.
do
r1 <- a 1
r2 <- b r1
r3 <- c r2
r3
This is about composing functions. It has nothing to do with mutability. It is just a convenient way to write the composition rather than using nested bind operators.You aren't allowed to touch the contents of the hot cell, instead you must send a robot arm into the hot cell. What is surprising though, is that the robot constructs another hot cell inside the hot cell and then merges it with the outer hot cell
The problem with monad is that it is a typeclass with not much meat on it, it would be more appropriate to talk about monad instances.
So so you're saying bitcoin should have been made out of monads?
This is a good description of one particular monad, the ST monad: https://wiki.haskell.org/Monad/ST
The ST monad (enclosing mutable state to use it in a linear, non-branching fashion) is indeed a good example of a monad.
Calling that the essence of monads is as accurate and helpful as calling it a burrito [1].
Future downvoters may want to try to reconcile any of the other common monads (Maybe, Either, List, State, Parser, Reader, Writer) against this enclosed/mutable/linear/non-branching definition and see if the essence fits.
This type of intuition always works on Monads. If you want to learn more about it I'd recommend to learn about the relationship between the Kleisli Triple and the monad. In reality this way of understanding this is just an intuition of how the Kleisli Triple works and how it is an equivalent to the traditional representation of the monad.
"The essence of *the ST monad* is to enclose a mutable state, providing only a set of carefully-crafted combinators for using it in such a way that you can't duplicate the state but have to use it in a linear, non-branching fashion."
I claim that the following 4 are incorrect: "The essence of *the Maybe monad* is to enclose a mutable state, providing only a set of carefully-crafted combinators for using it in such a way that you can't duplicate the state but have to use it in a linear, non-branching fashion."
"The essence of *the List monad* is to enclose a mutable state, providing only a set of carefully-crafted combinators for using it in such a way that you can't duplicate the state but have to use it in a linear, non-branching fashion."
"The essence of *the Either monad* is to enclose a mutable state, providing only a set of carefully-crafted combinators for using it in such a way that you can't duplicate the state but have to use it in a linear, non-branching fashion."
"The essence of *the Parser monad* is to enclose a mutable state, providing only a set of carefully-crafted combinators for using it in such a way that you can't duplicate the state but have to use it in a linear, non-branching fashion."
> In all cases an operation on an object of the monoidal type will mutate the wrapper type but not the wrapped type which always stays the same.I know of no type mutation in Haskell.
> If you want to learn more about it I'd recommend to learn about the relationship between the Kleisli Triple and the monad.
The original author has made an overfitting error, taking a specific learning about ST and incorrectly generalising it to all monads. If I were to relate it to Kleisli triples, wouldn't I be overfitting even worse?
"The essence of *the Kleisli triple* is to use abstract types to enclose a mutable state, providing only a set of carefully-crafted combinators for using it in such a way that you can't duplicate the state but have to use it in a linear, non-branching fashion."All four are correct. That is what they do in essence. What the author is describing the intuition of the Kleisli triple. The only thing that is questionable at all is the mutable part, but that can be excused because later the author goes back on it and clarifies it's merely an emulation of mutability
> I know of no type mutation in Haskell.
"Monad m" is type mutation. You are making the type m into a monadic type "Monad m" that still exposes all of the characteristics of the type m.
> The original author has made an overfitting error, taking a specific learning about ST and incorrectly generalising it to all monads. If I were to relate it to Kleisli triples, wouldn't I be overfitting even worse?
Kleisli Triples and Monads are strictly equivalent. A Kleisli Triple is just a different way of defining a monad. So it can't ever be "worse" than on monads because they are strictly equivalent.
Now as to the quote, the only real problem is "mutable" if you take it too literally. Enclosing a state around the element is what the unit function does, the wrapper itself is what the monadic type provides, and the sequencing of functions in a linear non-branching fashion to work both on the base type and on the state is what the join combinator does. Except for the whole mutability kerfuffle it seems like a fairly straightforward intuitive way to put the Kleisli Triple.