Comparing Haskell and Ruby, Part I

Share this article

Since I’ve started telling computers what to do (also known as programming), I’ve learned several languages. Some of these languages I’ve disliked (C++ with Boost), some I’m “in the middle” with (Perl), and some that I’ve liked a lot (Ruby, Python, Haskell, maybe JS). At first glance, Ruby and Haskell seem incredibly far apart, having almost no similarities. Ruby is an imperative language (albeit with some functional elements built into it), but there is no currying (one of the core concepts of Haskell) nor is there any provision for tail call optimization, making recursion an imprudent choice for many cases. Also, it is a very practical language – speed is put behind programmer efficiency. It was popularized by Ruby on Rails which, being a web framework, is probably as practical as it gets. Haskell, on the other hand, is a purely functional language (if you don’t know what that means, keep reading). Functions are absolutely essential to writing the language and are first class objects (more on this later). The language isn’t immediately practical – there’s quite a bit of reading you have to do before you can, say, build a small HTTP server (that’s actually quite easy in Ruby, with Celluloid. Looking a little deeper and taking in a bit of both languages (I assume you guys are literate in Ruby; if not, it is much easier than Haskell :)), we start to see very interesting similarities.

The Functional Paradigm

Traditional or imperative programming works a bit like cooking directions. You tell the computer to do this, then do that, and then the other thing. Functional programming works in quite a different way. Ruby is an imperative language. It may not be immediately obvious (if you haven’t thought about it) but, writing Ruby code reads like a set of directions to accomplish some kind of goal. When trying to write these directions, there is some changing and holding of “state”. This could meanm, for example, changing the value of a variable. Here’s the shocker – functional programming has no such thing as state. So, no changing variables! Now, think back to when you first learned programming, and you saw a statement like “x = x + 1”. My first thought when I saw this was – “Wait, what? Can’t you just cancel the x’s on both the sides, but, then you get an impossible equation…” With that, all of the math that you’d learned became useless. But, with Haskell (a purely functional language), it gives you your math back! Since variables can’t change, assignment statements like the above can’t happen! Imperative languages are quite free with side effects. Side effects are things that happen outside of the “working environment” of a method. For example, it means to change the state of the screen in a method by printing a line. But, side effects can be really horrible. When calling a method in an imperative language, you have no guarantee that it will do what you intend it to do. The method may return something completely different when called with the same arguments at a later time, because it may be affected by some external state. In purely functional languages (again, Haskell), side effects almost
can’t happen. This also gives us something called referential transparency. Referential transparency means that a function that we call will give the same result for a set of arguments, no matter what happens in the outside world. But, if side effects can’t happen, how are we supposed to print something to the console? Well, this is done by some magic called Monads, which basically try to stuff side effects into a completely pure, state and side effect free environment. An excellent example of a purely functional language is mathematics. There is no such thing as a side effect in math, because there’s nothing for side effects to effect! It’s all definitions and using those definitions. How does this compare with Ruby? This is where the languages are vastly different. Haskell is incredibly pure, where everything is squeaky clean and you’re not allowed to make a mess. Whereas with Ruby, if things aren’t done properly, code can become a tangled mess of state changes. Ruby also makes it much easier to perform side effects where needed, whereas with Haskell, it is a royal pain.

The Typesystem

Ruby, as most of us know, has a dynamic typesystem, which means that type detection is performed at runtime. As such, if there is some kind of problem with types of variables not matching, we only find this out a runtime (i.e. it will crash or throw an exception). This seems quite bad, because we might have programs crashing all the time. However, if you can keep track of your types throughout your program, it speeds up development quite a bit. If you’ve got any sort of experience with Java (shudder), which has a static typesystem, you know the problems a typesystem like Java can cause. Haskell has an incredibly strict static typesystem. This, initially, makes most Rubyists cringe and it definitely seems more irritating. But, let me tell you, it is a life saver. The Haskell typesystem has something called type inference
. So, in next to all cases, you don’t actually have to “write down” the types of any of the functions. Because of this, Haskell’s typesystem feels incredibly terse and very quick, while affording the convinience and security of a strict static typesystem. Ruby and Haskell differ quite a bit at first glance in this regard. One is highly dynamic and fluid, the other is rigid and incredibly strong. But, the end result that comes from both typesystems is an experience that is very agile and swift, letting you largely avoid thinking about types. However, as a personal preference, I like the Haskell typesystem better. I almost never notice the typesystem. It also gives the extra benefit of awesome typechecking at compile time, to the extent that if it compiles, it probably won’t crash. An important consideration is the data model. Ruby, like pretty much all other popular languages (except JS), has an OOP model. Haskell uses something called algebraic data types, which take quite some time to explain (especially to people who already have a concept of OOP.) Basically, these data types don’t have a much of a hierarchical structure, and, if used properly, can be incredibly powerful.

Wrapping It Up – For Now

Hopefully, this article gave you a general idea of what functional programming is, and started off the comparision between Haskell and Ruby. One thing is for sure. If you’re a Rubyist, it won’t hurt to pick up a little Haskell. It may even change the way you write code (it did for me). In the next article, we’ll cover more similarites and differences of Haskell with Ruby, such as built-in methods (and functions) as well as how the communities of both languages function. The LYAH guide is an excellent way to get started!

Frequently Asked Questions (FAQs) about Comparing Haskell and Ruby

What are the key differences between Haskell and Ruby in terms of syntax?

Haskell and Ruby have distinct syntaxes. Haskell is a statically-typed functional programming language, which means it requires explicit type declarations. It uses mathematical function notation and its syntax is concise and clear. On the other hand, Ruby is a dynamically-typed object-oriented language, which means it does not require explicit type declarations. Its syntax is more flexible and expressive, allowing for multiple ways to accomplish the same task.

How does the performance of Haskell compare to Ruby?

Haskell is generally faster than Ruby. This is because Haskell is a compiled language, which means it converts its source code into machine code before execution. This results in faster execution times. Ruby, on the other hand, is an interpreted language, which means it translates its source code into machine code during execution, which can slow down performance.

What are the advantages of using Haskell over Ruby?

Haskell offers several advantages over Ruby. It has a strong static type system which can prevent many common programming errors. It also supports lazy evaluation, which allows for efficient execution of complex computations. Furthermore, Haskell’s functional programming paradigm encourages immutability and stateless functions, which can make code easier to reason about and test.

What are the advantages of using Ruby over Haskell?

Ruby has its own set of advantages over Haskell. Its dynamic typing and flexible syntax can make it easier to write and read code. Ruby also has a large and active community, which means there are plenty of resources and libraries available. Furthermore, Ruby’s object-oriented paradigm can be more familiar and intuitive to programmers coming from other object-oriented languages.

How does the learning curve of Haskell compare to Ruby?

Haskell is often considered to have a steeper learning curve than Ruby. This is because Haskell’s functional programming paradigm and static typing can be quite different from what most programmers are used to. Ruby, on the other hand, is often praised for its readability and ease of learning, especially for beginners.

How does the community support for Haskell compare to Ruby?

Ruby has a larger and more active community than Haskell. This means there are more resources, libraries, and tools available for Ruby. However, Haskell’s community, while smaller, is known for its academic and theoretical focus, which can be beneficial for those interested in learning about functional programming and type theory.

How does the job market for Haskell compare to Ruby?

The job market for Ruby is generally larger than for Haskell. Ruby is widely used in web development, especially with the Ruby on Rails framework. Haskell, while less common in the industry, is often used in academia and research, and in industries where correctness and performance are critical, such as finance and data analysis.

How does the tooling for Haskell compare to Ruby?

Both Haskell and Ruby have robust tooling. Ruby has a mature ecosystem with tools like Bundler for dependency management and RSpec for testing. Haskell also has strong tooling, with tools like Cabal and Stack for package management, and QuickCheck for property-based testing.

How does the expressiveness of Haskell compare to Ruby?

Both Haskell and Ruby are highly expressive languages. Haskell’s expressiveness comes from its functional programming paradigm, which allows for concise and elegant code. Ruby’s expressiveness comes from its flexible syntax and dynamic typing, which allows for a wide range of programming styles.

How does the safety of Haskell compare to Ruby?

Haskell is often considered safer than Ruby. This is because Haskell’s strong static type system can catch many errors at compile time, before the code is even run. Ruby, being a dynamically-typed language, can only catch these errors at runtime, which can lead to more runtime errors and bugs.

Dhaivat PandyaDhaivat Pandya
View Author

I'm a developer, math enthusiast and student.

Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week