pure FP is just like pure OO
As someone who did OO for ten years and is doing FP full time, this statement is absurd. Why constraint ourselves?
You are not constrained in any way by FP, you just have to make everything explicit so programs are easier to read and reason about. There's nothing I can't do in a pure FP language. The world is not pure,
The world is not a touring machine either, does this argument have more substance or is it just an offhanded comment...? our programs don't become ANY better because of the IO monad
Do you actually have any experience with functional programming? Non rhetorical...it's such an odd thing to say.Programs absolutely become better when you encapsulate IO in a monadic context. 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. What functional language do you have experience with that would lead you to these bizzare conclusions? :)
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).
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".
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.
Another 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.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.
> 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
Yeah the overall win is what's subjective. To many, programming in a functional style, and embracing concepts like 'monads', is not appealing, regardless of that additional information.
There are lots of things we could do to add more information to our programs. We could write tooling that religiously enforces a certain amount of commenting for example. which would be 'more information'. But it's debatable/subjective that adds value overall, given the cost to developers.
> But are you arguing in favor of having less information?
Short answer, no, it's the manner in which it's conveyed, and the hoop-jumping required to do so that constitutes the subjective element.
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.
That said, most of my work is "doing stuff", not data manipulation, so perhaps that's the difference. Also "OOP" for me is C#, which has plenty of FP features (though F# style records and `with` syntax are annoyingly missing); if I was comparing Haskell to Java 1.0 code then I could imagine seeing things differently.
imo, types shouldn't be used to compensate for the lack of separation of concerns (simple data manipulation VS IO)
in my experience either IO absorbs everything but the most trivial trinkets that I wouldn't ever mess up anyway
You mean you never mess up business logic? IO should only really be used when you need to be interacting with the world, IE, network calls, UI, etc."Difficult" code is stuff that involves things like distributed transactions and whatnot. All that stuff has to be bundled in a big wad of IO anyway and so Haskell has nothing to help out with that in the first place (if there was a language that could, I'd be all over it). At least that's my experience. YMMV.
I half-expected this in my Haskell static site generator real-world-learning-project-of-sorts (reading files, writing files, "calling some smarty-pants composed combinators in between", nah not really just functions all the way down.. and somehow such a simple tool grew out of all proportion soon enough with ever more powerful markup notations to support etc pp..) but was profoundly surprised just how little of the code-base ended up in the IO monadic context and how much logic ended up as purely functional modules. Pleasantly eye-opening! (Sure even the IO monad is "purely functional" at least for the programmer though not the final assembler, but y'know-what-I-mean..)
Just an idle anecdote though
Almost all business logic is pure, and it can get pretty complex in my opinion.
Or in Greenspun's Tenth Rule Of Programming terms: Any sufficiently complicated Haskell/PureScript program contains an ad-hoc, informally-specified, bug-ridden, slow implementation of half of a Python VM trying to share state with an ad-hoc, informally-specified, bug-ridden, slow implementation of half of a JS VM trying to communicate with an ad-hoc, informally-specified, bug-ridden, slow implementation of half of a .Net VM.
Anyway I like typescript now too.
So we're back to FP... =P
TL;DR: The 'impurity' of the world is an illusion created by our brains.
I have a physics degree and I completely disagree. The world IS pure.
Think of it like this: Time is the successive application of a pure function that takes the old universe as an argument and returns the new universe. All science models the real world like this. This is the foundation of mathematics. Nowhere in physics or maths do we mutate anything. Even quantum applies this perspective. This is what leads to the many worlds interpretation of quantum.
What's actually going on is your brain is such a powerful illusion machine that it has convinced 'you' that the world is composed of 'objects' that 'change'. This is entirely inside your brain. It is a side effect of the perception process inside your brain. It does not mean the real world is actually composed of 'objects' that 'change'.
This illusion is so strong that we then go on to model the real world inside computers with 'objects' that 'change'. This is a mistake that leads to no end of problems.
Once you realise the world is immutable, and that the process of time is a function, and that what we see as time is actually a succession of immutable 'universe-values', you then start modelling your problems like this. And then you realise what a better fit FP is for modelling the real world. And then you realise why science models the world using mathematics... that is functions and values... which are immutable.
When I argue this with OO developers I ask them "Is the real world mutable, or immutable?" When they answer mutable, I then ask them to go back to last Tuesday and change their lotto numbers. They can't. It's almost as if the past.... is immutable! And the present becomes the past the very moment it comes into being. And the future is unknown.
The present also cant be changed. We can affect the future by using our muscles to apply 'forces' to the 'universe-value' thereby changing the way the time-function of the universe returns the new-universe value (the future), but we cannot reach in and alter any of these immutable values directly, not the past, the present, or the future.
"Many worlds" is more philosophy than physics, isn't the most accepted interpretation, and even going down that path leads to lots of edge cases that could still imply impurity.
Besides, if the world is pure, and OO is part of the world, then OO must be pure too so what's the problem?
Do you have other insane JS semantics in mind?
And yeah, F# looks brillant. Just wished it was not a .NET thing. Fable could interest me but it's just like bucklescript/reasonml: there is no momentum, no community, no libs. It would be a big leap of faith to heavily invest in it as an individual.
I generally like the FP approach with imperative escape hatches. Need more performance? Some code is actually more elegant in imperative form? Go for it. F# can do it, scala can do it too (unfortunately with some crappy java compatibility concerns to deal with)
Then what? OCalm is the other possibility, but the appeal of a larger ecosystem and easier mobile target by xamarin is what put me into F#.
>> Early preview of @reasonml bindings to ReactJS. Compiles to regular JS so interop/debugging is easy. Haven't been this excited since React!
At least that's my experience building a lot of single page apps. That could be seen as a weakness of SPAs. With fully separated pages, it's easier to mix technologies.