Haskell: Not pure enough?
blog.ezyang.com
blog.ezyang.com
The cost of bring full, absolute perfection are absolutely staggering. One of the biggest ones that is easy to miss is that you rigidly limit yourself to current implementations; consider the case of writing your perfect specification in 1998, then spending a lot of time right now wishing a metaphorical half your 64-bit machine wasn't sitting there idle. The benefits of this absolute purity vs. what we already have right now? Pretty small next to the costs. But that's just one example.
Besides, fixing some of those all but requires a new hardware and OS platform. Floating point is intrinsically nasty from a mathematical point of view, but as long as it is what the hardware supports, it's going to have to be in your language, for instance, unless you just want to give up on numerical performance. Some of the os module nastiness is hard to actually kill without going not merely the full-on JVM-as-OS route but beyond, as even the JVM exposes some OS differences.
But I am serious about the case-by-case thing. There may be some things that are wrong and are worth being fixed. My previous paragraphs dismissed the idea of fixing the totality of the problem but that doesn't mean any given thing may not be an improvement.
But Haskell also has a reputation for pushing the envelope. Who knew you could get away with not allowing side-effects in arbitrary expressions? Who knew you could actually implement a lazy language, and actually have it perform quicker than interpreted languages? These are things that could have been decided on a case-by-case basis, but Haskell changed the rules of the game by asking you, on a case-by-case basis, to opt out of these features. In the real world, this has a very powerful influence on the library ecosystem.
But I don't think I disagree with you. Just clarifying a point. :-)
safeAdd :: (SmallInt i) => i -> i -> Maybe i
safeAdd x y = if (maxBound - x) > y then Just (x + y) else Nothing
`maxBound` would be a member of the `SmallInt` typeclass, with different values for `Int32, `Int64`, `Int23`, etc.Why aren't Haskell's SmallInt functions parameterized over Int size, anyway? Of the points brought up in the blog post, this one seems the easiest to fix.
Purity means that the result of an expression is the same while the program is running. These calculations may differ if run on different computers or sometimes even if run at different times on the same computer, but once you run them you can be reasonably sure that they return the same result while the program is running.
None of the examples are massively series, but hopefully it should prove the point that this topic matters.
* I like knowing explicitly what kind of integers I'm working with and plan on using the full 32 or 64 bits available to me.
* IEEE floating point issues will be around forever. If you want something more precise, store the numerator and denominator, or factorization.
* foldr doesn't have to be implemented recursively.
IEEE actually gives a consistent functional specification for arithmetic that fits purely functional programming pretty well.
I used to program in Haskell for fun and school and I liked it. I find it very well thought out language. I may very well come back to programming in Haskell when I encounter a suitable project.
But there is a tendency among Haskeller's to get too caught up in praising purity and laziness, while ignoring the nice practical aspects of the language that could enable it to rise to be an even greater language.
I'm not saying that author is guilty of this, this is just a general observation. And I must admit that I'm not quite up to date of what's up with Haskell. My point is that Haskell is great for reasons other than purity and laziness, too.
"I want Haskell to be most useful only in specific, limited situations where puritanical program correctness is imperative" is a legitimate answer to this question, as is "I want Haskell to be practical enough to be general-purpose". And if a programmer looks at a problem and says "Haskell isn't right for this situation; I'm going to use something else", then you or I, a Haskell advocate, may be okay with that.