6 ms·
I don't disagree with your major point - "companies that invest in [[functional programming languages with a strong typing system]] are going to start seeing ma
by meric 13y ago
I don't disagree with your major point - "companies that invest in [[functional programming languages with a strong typing system]] are going to start seeing major dividends in terms of productivity and agility over the lifetime of the company." Haskell in particular I'm not sure of - the 'code rot' could easily manifest itself in performance. Haskell's laziness makes slow code and code that use up a lot of memory hard to locate, and at times require significant refactoring, to correct, though this is offset by haskell's type system somewhat...
You can see this manifesting in the project of the article's author under the "Not All Sunshine and Rainbows" section.
What I'm getting at - Bad code can be written in any language. IMO what's more important with regards to the language is how easy does it make to fix it.
I've only used haskell for my thesis project as well as having toyed with it in my free time now and then over the past two years, and have no commercial Haskell experience, so perhaps someone with more experience can chime in...
EDIT: A Haskell project I was working on: http://stackoverflow.com/questions/21654081/how-do-i-optimise-this-haskell-limit-order-book-with-code-reports-graphs http://stackoverflow.com/questions/21654081/how-do-i-optimis...
- tel 13y agoSo far as code leaks go I think the professional story is divided. Everyone runs into them, some people learn to fix them, those that do tend to think of them as a little annoying but not significantly more so than profiling and tuning strict code. Fortunately, outside of space leaks the Haskell runtime is actually really quite fast. At the end of the day most of your code which isn't leaky (buggy) will be really fast almost for free. But that second step can be painful right now. The tools exist to profile and debug space leaks, but they're not cohesive and require a fair amount of black knowledge. It's also fairly murky as to how to escalate: if you've identified your problem area, strictified it a bunch, and it's still broken... well what then? The answer seems to be growing that internal expertise. There are enough people out there writing enough stuff that a dedicated student of the runtime can learn all of the tricks needed to really attack failures like that—profiling, unboxing, reading core, figuring out the inliner, and a variety of style guide hints to making things all work smoothly (e.g. avoid the Writer monad).
- meric 13y agoUpvoted. "The answer seems to be growing that internal expertise." Or you can go with OCaml. :)
- mamp 13y agoOr F#, if you are using .net or mono. It's pretty well integrated into Visual Studio these days, and quite good in Xamarin Studio.
- platz 13y agoSadly, although the performance of mono is good enough for most things i.e. GUI, it's several factors slower in performance-critical applications. Although I'm excited about F#, the experience in Visual Studio is really great.
- tel 13y agoSure, or any strict language. There are a lot of benefits to laziness though even before you start to consider other Haskell/OCaml deltas. Laziness provides a much better platform for separation of concerns which has enabled Haskell programs to have an unheard of degree of decomposition and reuse. As always, it's a tradeoff. At this point, I don't personally feel afraid of debugging core or profiling space leaks. I don't feel like I'm much more than 50% up to date on techniques to fix them... but when they arise I have little trouble eliminating them. Lazy resource deallocation is a problem of lazy IO. The solution is to not use lazy IO and that's tremendously tenable today due to libraries like pipes and conduit.
- meric 13y agoI agree. Would like to note I've spent more time trying to optimize this[1] than writing code, however. http://stackoverflow.com/questions/21654081/how-do-i-optimise-this-haskell-limit-order-book-with-code-reports-graphs http://stackoverflow.com/questions/21654081/how-do-i-optimis...
- dasil003 13y ago> What I'm getting at - Bad code can be written in any language. IMO what's more important with regards to the language is how easy does it make to fix it. Hm, not sure I agree with this. As a professional rubyist I am aware of the wide variety of bugs that can and do happen because of things that Haskell simply wouldn't allow you to do (at least without pathological abuse of the language that would never pass a code review). The thing that makes Haskell special to me is just how much the commitment to functional purity and a powerful type system buy you in terms of decreasing the surface are of potential problems. You've rightly pointed out that Haskell has its own memory and performance pitfalls that are very difficult to debug, but my instinct is that those things, while perhaps being showstoppers for embedded and realtime systems, are not intractable in a typical server environment, and that it's orders magnitude easier to improve the tooling around detecting and solving these problems than it is to ever make a language like Ruby code safer and require fewer tests. Of course I'm an utter beginner at Haskell, so I don't have a real sense of its downsides at scale, so take my opinion with a teaspoon of salt.
- copergi 13y ago>Haskell's laziness makes slow code and code that use up a lot of memory hard to locate, and at times require significant refactoring, to correct This is largely mythology built up around a misunderstanding of the grain of truth at the core of it. Lazyness can create pathological performance issues, just as strictness can. 90% of the time neither matters, 5% of the time you need strictness, 5% of the time you need laziness. Using strictness in haskell is very simple, and knowing when you need to is very easy to learn. The profiling tools make it incredibly obvious when laziness is causing a problem. And I can't even imagine a case where it requires significant refactoring. It is generally adding a couple of "!"s or importing Module.Strict instead of Module.Lazy.
- tel 13y agoI'd like to add that for the 90% of the time it doesn't matter, 95% of that time you could use a total language. This is one of the joys of using a total language: seeing what's still easy!
- chriswarbo 13y ago> This is largely mythology built up around a misunderstanding of the grain of truth at the core of it. I agree. I've encountered a few space leaks in my Haskell code, but it's always been pretty easy to track down: profile the memory usage and look for a conspicuously huge peak. It will usually be fixable by forcing an intermediate result, or using a different recursion strategy (eg. a fold instead of explicit recursion). Haskell functions tend to be so small and single-purpose that there are no knock-on effects of doing this refactoring. I think there's a perception that 'Haskell is difficult to debug', whereas the reality is more like 'Haskell will reject all of the easy bugs'. In other words, the average difficulty of a Haskell bug may be higher, but the density is less.
- ufo 13y ago> eg. a fold instead of explicit recursion Wouldn't adding some bangs in the patterns kind of do the same thing as using foldl'?
- thinkpad20 13y agoI really wish Haskell weren't lazy by default. Laziness is great in places, allows you to write very declaratively, and even allows for some computations that would otherwise be impossible or less efficient. However, most of the time, you envision and write code as a series of steps (even though theoretically in a functional language, you're just writing an expression). In a practical matter, the cases in which lazy evaluation becomes desirable exist, but are limited. Most of the time, you want, and expect when you write it, your code to be evaluated strictly. Of course you can enforce strictness manually with `seq` and bang notations and the like, but this clutters up your code and might not even matter if you're using library code which doesn't do the same. IMO Haskell would greatly served by having laziness be opt-in, not opt-out. But its pretty ingrained at this point, and there doesn't seem to be too much of a push to change it (who knows how much extant code would be broken by such a change).
- tel 13y ago> However, most of the time, you envision and write code as a series of steps Perhaps counterintuitively, I disagree here. I think using laziness enough will eventually change your mind that most code must be thought of in such discrete steps. Instead, I tend to keep in mind and think constantly about how a computation might be partially delivered and how it might be consumed. This is part of the declarative promise of laziness playing out, I feel. Ultimately I don't think there's a "right" decision. I'm comfortable in strict and lazy languages. I do think everyone should experience both strict and lazy evaluations enough to no longer be worried about them and instead just see each as another, separate form of computation. At the very least it'll make you much more aware of what evaluation order and normalization feel like. (I'd also highly recommend everyone plays with a total language for a while, too. That feel is quite distinct.) At the end of the day, I feel like having laziness by default and picking around for places which ought to be strict is very dual to having strictness be default and picking around for places to make lazy. Both are pretty annoying. I do think people are generally more sensitive to problems of excessive laziness than they are to problems of excessive strictness. Manually wiring around stopping criteria and consumption control through all of your (no longer decomposable) loops/recursion is the price of strictness. Both problems are helped by tooling, as well.
- implicit 13y agoIn practice, I've found space leaks in Haskell code to be a bit analogous to extraneous copies in C++ code or NullPointerExceptions in Java: They're usually not a huge problem, but sometimes you get it wrong even if you're experienced and know what you're doing. We've only had one really disasterous space leak and it was caught and reverted right away. The hardest ones are generally the slow ones where the servers take 3-7 days to run out of RAM and fall over. If you never go more than a few hours without a code push, you might not even notice it.
- jfischoff 13y agoFWIW one reason the service mentioned in the blog was so fast was because of laziness. Because it didn't need most of the request, the work required to parse it was mostly avoided.