Rust vs. Haskell

  vs.

Today we looked at the following article, which compares Rust and Haskell:

https://serokell.io/blog/rust-vs-haskell

Even though I did some dabbling in Haskell, I never understood how close the two are. Currently I think I’m quite proficient in Rust, so I can follow the article quite well on that side.

While the basic concepts seem to be more or less the same, which is a surprise to me, it gets a bit different. But not too much:

Algebraic Data Types

It is interesting to think that the separation of struct and enum in Rust is not necessary – Haskell uses a single data keyword for both. I like the partial field accessors in Haskell, which allow to simplify access to a value in an enum:

data Croissant 
  = Plain {price :: Double} 
  | WithFilling {filling :: String, price :: Double}

let plain = Plain 1.75
print $ price plain

While the same in Rust doesn’t work:

enum Croissant {
  Plain { price: f64 }, 
  WithFilling { filling: String, price: f64 }, 
} 

let plain = Croissant::Plain { price: 1.75 }; 
println!("{}", plain.price)

It is nice that the pattern matching between Rust and Haskell is very similar. Also, this is one of the main reasons I started learning Rust: in go you’re very restricted in what goes into an enum (well, const). And treating those is much worse than using enum in Rust, which can also hold values.

Failure Handling

Here, too, Rust and Haskell are quite similar. Even though it came as a surprise to me that the Result in Rust corresponds to a Either in Haskell. And Either has as a convention that Right is success, and Left is failure. I hope there is nothing political in that convention 🙂

It seems that Haskell is very much into avoiding any errors, as the post states:

Haskell developers painstakingly try to use types to avoid the need for errors in the first place. If you get approvals from at least two other developers and CTO, you can use error.

A nice way of saying: NEVER.

I leave the Polymorphism and Advanced topics out – at least for the Advanced topics, the differences between Rust and Haskell show up very strong. It seems difficult to compare them in these cases.

Functions and Functional Programming

This part is again very similar between the two languages. Having struggled for months to pass async closures in Rust, I would’ve liked some comment on this. It is not pretty in Rust to do this.

While most of the things are possible both in Rust and Haskell, one thing is missing in the latter: you cannot have Associated functions and methods. Meaning: you cannot create a method on a data. That surprises me, as to me this describes naturally dependencies between data and how to handle it. So I would like to know how Haskell handles that. But the article only says:

In Haskell, we can’t and don’t.

It probably makes sense with regard to Purity in Haskell.

Things to Worry About

Not surprisingly, all Rust worries about is ownership. Haskell is more diverse, and worries about Laziness, Purity, and Higher-order programming. At least the first two concepts can also be used in Rust: both Laziness and Purity come up from time to time.

But there is no such thing (yet) as Higher-order programming in Rust. Even though the article shows how Rust has these problems solved in another way.

Conclusion

I was quite surprised by this article to see how close Rust and Haskell are. Was Rust inspired so much by Haskell? Or are these just two approaches to getting languages “right”, and they came out similar?

— Linus