Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I'm not saying the type makes no sense, I'm saying the article doesn't communicate any value to people who aren't sold on the idea of monads before they go in. Like, if you're explaining functions to a newbie programmer, you don't just take a bunch of lines of code, replace them with `do_the_function()`, and act like you've made the program better. Obviously all those lines are still hiding in the function definition somewhere and your indirection has only increased complexity. You have to show that using functions to extract patterns from around the program improves elegance or expressiveness overall (e.g. by reducing total lines of code). I've never read a monad tutorial that does this in a way that (comparatively) simple higher-order functions wouldn't do just as well.

edit: to expand on that last sentence, the example under "Ad hoc solution: Promises" is more expressive to me than the author's monadic code, because a) it's more explicit about what depends on what, and b) the ".then" method name gives you a hint about what sort of computation is actually going on. Replacing "then" with "try" or "each" makes the code work just as well for the null-checking and for-loop examples.



> I'm not saying the type makes no sense, I'm saying the article doesn't communicate any value to people who aren't sold on the idea of monads before they go in. Like, if you're explaining functions to a newbie programmer, you don't just take a bunch of lines of code, replace them with `do_the_function()`, and act like you've made the program better. Obviously all those lines are still hiding in the function definition somewhere and your indirection has only increased complexity.

I'm not convinced. Imagine a tutorial for the foreach construct: it would show code for iterating over a list, code for iterating over a set, and code for iterating over an array, and then a foreach loop. Would you say that obviously the iteration code is still hiding somewhere and your indirection has only increased complexity? Introducing a common interface - which is proven by the use of a common syntax - is something that we recognise as valuable, I think.

> You have to show that using functions to extract patterns from around the program improves elegance or expressiveness overall (e.g. by reducing total lines of code). I've never read a monad tutorial that does this in a way that (comparatively) simple higher-order functions wouldn't do just as well.

FWIW my own effort is https://m50d.github.io/2013/01/16/generic-contexts


An interface is a kind of relation between things that would otherwise be separate. So yes, I'd say that establishing the interface by itself increases complexity slightly.

However, there are lots of situations where one may want to substitute one enumerable type for another, and thus lots of opportunities to recoup that complexity. The first time the interface lets me write one function instead of two (say, a batch processing function that can deal with objects in an Array or those being streamed from an IO, because they both implement foreach), that's a win.

I have to think a lot harder to come up with a situation where I have an object that might be an Option and might be a Future, and I don't care which type I have. It doesn't seem like it would ever come up in business logic, so we're probably looking at some sort of mid-level abstraction that depends a lot on the code on both sides of it. Maybe that's why writing a decent, concise tutorial is so hard.

I like your article. You make explicit that being able to use Options and Futures interchangeably is the objective, and your example code actually depends on all the monad behaviors instead of just flatMap (I think - Scala is a foreign language to me). I still don't know how often those circumstances come up in practice, but maybe with experience I'll start seeing the patterns more often. Thanks again.


> However, there are lots of situations where one may want to substitute one enumerable type for another, and thus lots of opportunities to recoup that complexity. The first time the interface lets me write one function instead of two (say, a batch processing function that can deal with objects in an Array or those being streamed from an IO, because they both implement foreach), that's a win.

> I have to think a lot harder to come up with a situation where I have an object that might be an Option and might be a Future, and I don't care which type I have. It doesn't seem like it would ever come up in business logic, so we're probably looking at some sort of mid-level abstraction that depends a lot on the code on both sides of it. Maybe that's why writing a decent, concise tutorial is so hard.

I see where you're coming from. Monads are parametricity rather than substitutability: an Option and a Future are similar to each other in the same sense that a List<Int> and a List<String> are similar to each other. You'd never have a situation where you didn't care if you had a List<Int> or a List<String>, but there are still functions like sort() or find() or foreach() that are useful at the generic level.

And it's hard to do a good concise monad tutorial because they're an abstraction over an abstraction. Really a good tutorial would probably need three different examples - say Option, Future, and Writer - but then you'd probably need three examples for each of those to show why they're a worthwhile thing to be using in the first place.

> your example code actually depends on all the monad behaviors instead of just flatMap (I think - Scala is a foreign language to me).

flatMap/bind is the most important part - if you have a well-behaved (i.e. associative) flatMap you're 90% of the way to being a monad. I did use "wrap" for the base case (empty list), which is the kind of place it usually comes up. Don't get me wrong, it is important, but you can go a long way with just flatMap.

> I still don't know how often those circumstances come up in practice, but maybe with experience I'll start seeing the patterns more often.

Once you're used to them you see them everywhere - it's such a simple and general interface. I said anywhere you'd have a cross-cutting concern; another heuristic might be anywhere that you'd like to use the command pattern if you were "doing it properly", but there would be so much overhead to actually defining a command type. Simple things like authorisation - http://blog.sigfpe.com/2007/04/homeland-security-threat-leve... is slightly a joke, but it's something you can apply genuinely in an application that has some concept of being logged in at different privilege levels.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: