5 ms·
This is a really good way of explaining monads. Generally, when people ask about monads, they're not really asking 'what' monads are - they're asking 'why' and
by kpmah 9y ago
This is a really good way of explaining monads. Generally, when people ask about monads, they're not really asking 'what' monads are - they're asking 'why' and 'how' you use them.
The advantage shown here is that Haskell has special syntax for monads, and this single abstraction can be used for multiple features that many other languages have specialised syntax for.
- majewsky 9y agoThat can also be seen as a disadvantage. There is value to having different things look different.
- klmr 9y agoThe difference is given by the code context (which is unfortunately entirely missing from the article). What’s shown here are the things all these patterns have in common. The whole point of abstraction is to have different, but related, things look the same. Haskell (and these examples) certainly raise the level of abstraction to extremes (compared to other languages). But as long as the context (explicit type annotations, if necessary) make it clear what the code does, I don’t see this (even conceivably) as a disadvantage.
- xenomachina 9y ago> But as long as the context (explicit type annotations, if necessary) make it clear what the code does, I don’t see this (even conceivably) as a disadvantage. I spent 3 years trying to learn Haskell, and I never found this clear. When you see a "do" block, where do you look to figure out what it's actually doing?
- dllthomas 9y ago> When you see a "do" block, where do you look to figure out what it's actually doing? If you need to know, you look at what consumes the result. If it's abstract (say it's a top level binding `... -> m a` where the m is abstract) you don't need to know "what it is actually doing" - it should be correct for any choice of `m`. Whether this stuff is easy to find/follow certainly depends on the quality of the code, as well as your experience. It's not something I struggle with, working day-to-day in Haskell.
- dmitriid 9y ago> you don't need to know "what it is actually doing" - it should be correct for any choice of `m`. I don’t know what it’s doing, but it’s correct. :-/ So what is it doing that’s correct? Or is it some abstract correctness?
- dllthomas 9y agoIt's not abstract correctness, it's satisfying contracts up to an interface. Take `sequence :: Monad m => [m a] -> m [a]` That takes a list of actions and gives us an action that runs each in turn and collects the results in order. The correctness relative to that description is clear regardless of whether each input action is threading state or handling failure or printing to the screen.
- dmitriid 9y agoThen this clearly doesn’t answer the original question, does it?
- deleted 9y ago[deleted]
- dllthomas 9y agoNot on its own. Fortunately, it wasn't the entirety of my answer to the original question. When you're writing something like `sequence`, you don't need to know the implementation of the interface you're working against. As you get comfortable in Haskell, more things are "like `sequence`". There will always be things that aren't - for those, as I said, you should look where the value is consumed. And as I neglected to say, you can always add a type annotation when things get unclear.
- dmitriid 9y agoAh, the old Java adage: any abstraction can be solved with many more layers of abstraction.
- leshow 9y agoLook at the return type of the function and you can tell what instance it's using, if it's using something that's a type variable, then it's instance isn't important, just it's interface.
- tikhonj 9y agoI work on largeish commercial Haskell codebase and I never have to look anywhere to figure it out—I know what the do block is doing because I know what function it's in and what the return type is. With a bit of experience I started keeping track of this context subconsciously so the question just doesn't come up. Haskell code tends to rely on context quite a bit. This does make it more difficult to learn, but once you're over the hump, context is something you end up understanding automatically.
- xenomachina 9y agoWhat makes this confusing for me is that this is backwards from the way expressions work pretty much anywhere else. It should be possible to know the type of a sub-expression without knowing anything about the expression that contains it. That is, start at the leaves, and work your way up. In Haskell, sometimes you have to go the other way. It's like trying to read a novel where some chapters randomly assume you know what happens several chapters later.
- default-kramer 9y agoI remember a great quote by Bjarne Stroustrup along the lines of "people want big, loud syntax for things they are unfamiliar with and small, quiet syntax for things they are familiar with." It made me realize how arbitrary some of my opinions on language design were/are. On the posted code, I'm totally OK with the Maybe monad, but the State monad makes me a little uneasy. If the state is an important part of the code, I want to see it! But would I feel the same way if I were more familiar with the State monad?