Monday, March 09, 2009

Haskell vs. OCaml, or the ravings of a monomanic insomniac

Until fairly recently, I was a hardcore Haskell hacker who saw little reason to go elsewhere for needs of a higher-than-C level. Haskell is beautiful; Haskell is clever; Haskell has Parsec. A couple of weeks ago, I started using OCaml (after having used ML for a couple of semesters as an undergrad) and realized that you can get a lot farther in life if you are not limited to writing pretty code*.

Since then, I've gone back an forth between "OCaml is the future" and "But Haskell is so pretty." Here are my notes on OCaml vs. Haskell.

Pro-Haskell:
  • Haskell does datatype constructors right. As in, Haskell datatype constructors are functions whose types are the type of the constructor. For instance, if we have a data type data Thing = C1 Int Int | C2 Bool, we get constructors of types (C1 :: Int -> Int -> Thing) and (C2 :: Bool -> Thing). In OCaml, constructors take explicit tuples. The analogous constructor C1 would need to take something of the form ([int], [int]), not just something of type (int * int).
  • Haskell does type classes right. Not just type classes, but type class related utilities like deriving. Type classes are often nice for clever things but always nice for development. Being able to derive Show and Eq gets rid of a ton of boilerplate. Not believing in function overloading makes me not believe in ML! >:o
  • Haskell is way prettier. Small things make Haskell code way easier to read and maintain. (For instance, the support for defining things below functions with where instead of binding everything for let. I should not have to trade off cluttering my toplevel namespace with cluttering my function definitions!
  • Because Haskell is so clean and concise, it makes you produce prettier code in other languages.
  • Higher-rank polymorphism and the ability to write down my forall types is very convenient.
Pro-ML:
  • You can code without being constantly clever! In my senile senescence (which is also absolutely alliterative), I see this as a huge plus. ;)
  • Not having to work in monads all the time to deal with state in any kind of okay way is a huge productivity plus of SML/OCaml. Don't believe me? I have the following points: 1) 3D IO Arrays, 2) gensym**, and 3) monad transformers (yuck!).
  • OCaml has very nice library support (Batteries, arrays, etc.).
  • OCaml seems to have a larger user base, so there are more people doing stuff in it, more people to ask when things go wrong, etc. etc.
  • Though ML code is more verbose and generally less pretty than Haskell code, it disallows a lot of the clever use of syntax that obfuscates the meaning of Haskell code.
The conclusion is that while Haskell leaves a nicer taste in one's mouth, OCaml might be better for practical purposes, especially if you want to use 3D mutable arrays. It all depends on what you want to do.

* According to some fairly high standards of "pretty."
** Generate fresh variable names, for instance "__tempvar0." Note that being able to keep some state is nice so you can just increase your variable count each time.

6 comments:

Jesse Tov said...

Very interesting. I must say I find Haskell more practical for getting things done than Ocaml, and I've written plenty of both by now. Why? 1) Type classes 2) monad transformers 3) Great FFI 4) generally well-thought-out language design (such as what you mention about data constructors being actual curried functions).

Things I like about Ocaml: 1) Ocamllex and Ocamlparse are much nicer than their counterparts in other languages (and sometimes Parsec doesn't cut it). 2) Camlp4. 3) Functors (however, SML functors are better).

For what it's worth, Ocaml does have arbitrary-rank polymorphism. It's just that the only place you can write qualifiers is inside record types. So, if you want a function that takes a polymorphic argument, you need to declare a record type with the argument type that you want, and then have the function take the record type. Of course, if you want foralls under a whole pile of arrows, you'll need a whole pile of record types. You can also use record types with implicit foralls to do polymorphic recursion, which is kinda hot.

Main Ocaml annoyance for me: EVERY single minor version bump breaks my code. I haven't yet figured out why 3.09 broke my 3.08 code and 3.10 then broke my fixed 3.08 code. I haven't yet figured out why 3.11 broke my current 3.10 code. Oy!

Anonymous said...

[url=http://sunkomutors.net/][img]http://sunkomutors.net/img-add/euro2.jpg[/img][/url]
[b]selling softwares, [url=http://sunkomutors.net/]educational discount microsoft office[/url]
[url=http://sunkomutors.net/][/url] adobe photoshop cs4 color settings sell my softwares
best price for software [url=http://sunkomutors.net/]academic version, adobe creative suite 4 premium[/url] software market discount
[url=http://sunkomutors.net/]nero 9 torrent[/url] buy mobile software
[url=http://sunkomutors.net/]free nero express[/url] buy photoshop cd
isn software canada [url=http://sunkomutors.net/]of software stores[/b]

Anonymous said...

What about stacktraces/debugging/etc?

Danny Gratzer said...

Looking back a few years later I'd say Haskell is far more practical. Why? Hackage. It has quite large collection of high quality libraries that really boost productivity.

Plus lens is very nice.

Franklin Chen said...

The cool thing is that today, as 2014 approaches, there has been considerable improvement in both the OCaml and Haskell communities toward libraries, packaging systems, tutorials, and even startups devoted to promoting the languages.

I still think Haskell is more prominent, however, possibly because of the origins of OCaml in France rather than in an English-language-dominant environment.

Spiros Boosalis said...

"2) gensym"

lol yes!

i wrote a compiler with a friend (and had to learn haskell at the same time). making unique identifiers was literally one of the hardest parts for me.