Haskell is a mature, statically typed, functional language which was recently compared to Ruby in an attempt to solve Euler #25. In this post I'll share the code, the benchmark and add a Clojure version for those interested.
Normally it's bad to start with the disclaimer, but for the sake of all you angry young men with ill tempers I'll say it anyway: Similar to the Clojure Vs Ruby & Scala post this is in no way an exhaustive comparison between the languages, its intended at a superficial glance at a simple challenge, namely Euler #25, all in the name of good clean fun. Haskell is by far too vast, too impressive and too powerful to be fully dealt with in a simple exercise like this, and the Ruby code is still running :)
Create a Fibonnaci sequence and walk through it, until you find the first number which is 1000 digits. The Fibonnacci sequence is exceedingly simple. Its seeded with 0 1 and all consecutive values n, are generated by calculating n-1 + n-2.
0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181.....
All 3 versions are compact and powerful - I'm assuming they're idiomatic, but if I'm wrong let me know. Like I said - If you can produce a better version, please submit it instead of taking this as an invitation to a flamewar :)
Ruby goes like this:
require 'matrix' limit = 10**999 FIBONACCI_MATRIX = Matrix[[1,1],[1,0]] def fibonacci(n) (FIBONACCI_MATRIX**(n-1)) [0,0] end i = 1 i+=1 while fibonacci(i) < limit puts i
The real trick here is building the Fibonnacci seq (fib-seq), which is done by applying the Matrix form, which is a clever way to leverage some differential equations in order to produce the sequence. According to the author this runs faster than a regular memoized variant.
Haskell code looks very different from both Ruby and Clojure, but for a simple task like this is reads almost like plain English:
limit = 10^999
fibonacci_numbers = 0:1:(zipWith (+)
fibonacci_numbers (tail fibonacci_numbers))
index = length w where w = takeWhile (< limit) fibonacci_numbers
main = do
putStrLn(show(index))
First the limit is defined as the first number having 1000 digits, and then a sequence seeded with 0 and 1. When you have a sequence which requires a constant look-behind of n-values, it can be represented as a recursive set of vectors. I call that a rule of thumb, Christophe says its a theorem. One thing which is really great about the Haskell code, is the automatic currying which enables the author to do the elegant w = takeWhile (< limit). Although this example is not flaunting it, Haskell is very different from Clojure in that its statically typed and there's been many discussions back and forth on which is to prefer, dynamic or static typing. The truth is, no one answer fits all but there's a simple test:

If the arrow and the explanation actually helped you, then static typing is for you.
To produce the fib-seq, we can mimic Haskell almost point for point, but where Haskell has direct support for sequences in the syntax, I need to call a few functions:
(def fib-seq (lazy-cat [0 1] (map + fib-seq (rest fib-seq)))) (let [limit (.pow (BigInteger/TEN) 999)] (count (take-while #(< % limit) fib-seq)))
The noticeable exterior differences is the call to lazy-cat and the anonymous function, which all readers of this blog should be able to read without any explanation. Under the hood, Haskell is fully lazy where Clojure is now Chunky-lazy. Chunked-seqs mean that I work with the sequences as if they were fully lazy, but under the hood Clojure is realizing the sequence, one chunk at a time. If I take 50 values, 82 may in fact be calculated - this is for improved performance without wrecking the use of infinite sequences. According to one of the authors of this book (which looks extremely promising btw, so go look), Rich Hickey has provided an example which eliminates the need for chunked seqs: here. That is idiomatic Clojure running faster than our old seq implementation written primarily in Java.
So the usual indicators for expressiveness and performance are LOC and runtime speed, so here we go:
| Language | LOC | Runtime |
| Clojure | 3 | 0.021s |
| Haskell | 6 | 0.007s |
| Ruby | 9 | 7.1s |
Last time I benchmarked Ruby it also came in... a little late, and some commentators suggested trying out other Ruby compilers - The truth is however, that small benchmarks like this really show very little and if you are working in a performance critical zone, you'll want to test something which mimics the actual project and the actual environment. Secondarily, neither Haskell nor Clojure are optimized for performance which accounts for some of the extra Ruby code.
The lesson we can take away, is that Haskell and Clojure are blazing, and Haskell is blazing to the point where I'm not finding words good enough to describe it.