|
|
|
|
|
by ezrast
2140 days ago
|
|
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. |
|
> 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.