5 ms·
> The entire point is to demarcate what functions interact with the world and which don't. This makes testing easier, reading code easier, composition easier.
by allover 10y ago
> The entire point is to demarcate what functions interact with the world and which don't. This makes testing easier, reading code easier, composition easier.
This is 1. a tradeoff , 2. subjective. Words like 'bizarre' aren't really necessary, and come off as feigned surprise (passive aggressive).
You think a function being easier to test (without reaching for extra tools like mocking libraries, presumably), justifies needing to write and understand 'monads' in order to interact with the real world.
Another programmer finds myObject.doExplicitThingToWorld() far more expressive and easy to understand and is very familiar with the mocking tools/practices they need to test that.
As for composition ... well composhmishion. It's so rare you can actually compose your business logic/app-code (beyond the original use-case you wrote the thing for, which you might well have chosen to write in a 'compositional' way).
It's neat for frameworks and libraries to create composable stuff but it just doesn't come up as often as we'd all like to hope in our day-to-day code in my experience. And if you really want to compose something OO absolutely has ways to do it.
(So composition is not the big win over OO some FP fans make it out to be IMO).
- boubiyeah 10y agoAgreed. I've used many nice libs using various monads, applicative builders, functors, yada yada under the hood; It can make the libs more pleasant to use for an end user for sure. But telling people that you should write EVERYTHING using this style because it's "objectively" superior strikes me as being almost religious. Surely, you don't need IO monads to write, say, an API server.
- chriswarbo 10y agoAt least in Haskell, things like `Monad`, `Functor`, `Applicative`, etc. are just interfaces ("type classes"). You can ignore them if you like, so you don't need IO monads, or any other monads, to write, say, an API server; in the same way that, for example, in Java just because you have an Iterable value doesn't mean you need to iterate over it. In comparison, `IO` is a type (actually a "type constructor", AKA a generic). Since many useful functions (e.g. `readFile`) return values of this type, it's pretty hard to avoid; although you can probably get quite far by ignoring types completely and having everything inferred. In that sense you do need `IO` to write, say, an API server; but I think that's pretty reasonable, since you want you server to read input and write output. Whether or not `IO` is a `Monad`, `Functor`, `Monoid`, `Alternative`, etc. doesn't really matter for that. Of course, you can always wrap your code in `do { ...; }`, cause all the side-effects you like, and ignore the fact that behind the scenes it just-so-happens that you're using a monad; after all, that's what pretty much all imperative languages do! More seriously, I think that the Haskell community should try to avoid this habit of saying "the Foo monad", when "a Foo value" would be more accurate, since I think it can confuse new users about types, values, type classes and instances. In particular it can give the false impression (reflected in your comment) that writing simple programs in Haskell (or FP in general) requires learning fancy things like monads. In reality, that's no more true than claiming that before writing a Web site in PHP you have to learn inversion-of-control containers. They're a commonly used framework/scaffolding, but there's no reason to confront them before you've written a few applications without, and hence are able to appreciate why they exist and what problems they do/don't solve. This mostly seems to be a problem for IO and Maybe. In particular, "State monad" and "Reader monad" don't have this problem, since their values have more widely used names like pairs/tuples and functions, respectively. Likewise, I've not seen this happen with other type classes, like "it returns a Maybe functor", or "I need to combine two List monoids".
- boubiyeah 10y agoI think what I was trying to say is that not all monads are equal. While the List or Maybe Monad or a JSON validation applicative builder brings me instant value (composition, no nulls, accumulation of error and composition again) I always scratch my head when looking at the IO monad. But maybe that's because I mostly use scala, where Futures are used a lot and they cover 90% of my IO usage. In the case of Elm, what I dislike is that everything ends up being a Task/Side Effect/IO. Even asking for a value to a Javascript Money library. That, to me is an unacceptable tradeoff.
- runT1ME 10y agoAnother programmer finds myObject.doExplicitThingToWorld() far more expressive and easy to understand By definition, I can reason more about my function returning a monadic context than I can about theirs. I can get free theorems from my function, I can see clearly if I'm doing both input/output, (or just output), and I have laws to help me understand how I can compose this function with others. None of that comes for free when side effecting freely.
- deleted 10y ago[deleted]
- allover 10y agoAnd again that supposed benefit of yours is entirely subjective, no matter how objective you try to make it sound. To me that's not a good enough reason to write my code in that style, when to me (subjective), OOP models the world in a way that is more expressive, I/O is not a thing I need to run scared from, and the methods I write that mutate the world do so clearly enough to me, just in their naming.
- jamescostian 10y agoHow is their argument subjective? If I understand your argument correctly, you are saying that for example: > myObject.doExplicitThingToWorld() [is] far more expressive But if I put the word "than" after that, consider what you would type next. Are you arguing that "myObject.doExplicitThingToWorld()" is more expressive than "doExplicitThingToWorld(myObject)"? Because you could write code like that in the FP world, and it's basically the same as the OO world, except (assuming immutability) you'll also know that myObject is not changed after that call. But runT1ME is talking about how the FP equivalent would come with more information ("I can see clearly if I'm doing both input/output, (or just output), and I have laws to help me understand how I can compose this function with others"). This added information is not subjective. There objectively is more information. The stuff you conveyed in your OO code by naming a method "doExplicitThingToWorld()" can also be conveyed in FP code by naming a function "doExplicitThingToWorld()", but the OO world misses out on the information that monads bring (and monads are just an example of this). Sure, saying that "more information is not necessarily a good thing" is true. But are you arguing in favor of having less information? Because in that case, why isn't procedural-style programming better (subjectively) to you? After all, one could make the case that OO pollutes code with unnecessary information (classes and hierarchies) and that just like how FP overhypes composition, OO overhypes inheritance
- codygman 10y ago> Another programmer finds myObject.doExplicitThingToWorld() far more expressive and easy to understand and is very familiar with the mocking tools/practices they need to test that. Well hopefully said programmer knows their mocking/practices will not be nearly as exhaustive and fully understand the price they pay for a little initial gain in expressiveness. Perhaps correctness is of low enough importance it doesn't matterin their case, but I would hope an honest analysis is done.