Thanks for pointing that out. The author didn't emphasize that point, and it makes sense now.
Is it me, or was it a bad example for where Haskell "really shines"? I don't like the "use Haskell cause it has these really cool functions" approach. Feels so superficial.
Haskell is worth the effort, but I don't think the article's author did a great job of articulating why.
Some things I've noticed:
Haskell does not automatically admit an extra "null" value to every type, so you can ordinarily ignore NullPointerExceptions and the like. When you do need a nullable bit of data, you have to do some extra work: You must rename the type from "Foo" to "Maybe Foo" and change all the callsites. These callsites must test for null and specify what happens. (there exists a non-terminating explode() function if you really want it) The build will fail until every last case is covered. This is great for reliability.
Most data in Haskell is immutable. This encourages good programming practice, sure, but it really pays off when you start writing parallel code. Parallel Haskell is by far the easiest way I know to write fast concurrent stuff. On that note, Haskell's concurrency primitives are very well-designed.
Haskell's solution to callback hell is more general and powerful than anything I know. The "do" block is really just super elegant syntax sugar for a CPS chain.
Our unit test suite does not intermittently fail. We restrict side effects such that our build will fail if a test tries to do non-faked I/O. It took a bit of effort to build, but normal use is effortless.
It wasn't so much a bad example so much as it was a trivial one. Perhaps a more powerful one (that displays the advantages of lazy evaluation and higher-order functions) would be the function to generate an infinite list of Fibonacci numbers.
Is it me, or was it a bad example for where Haskell "really shines"? I don't like the "use Haskell cause it has these really cool functions" approach. Feels so superficial.