Trying OCaml 🐫
Tuesday, February 20, 2018 :: Tagged under: culture engineering projects plt. ⏰ 4 minutes.
Hey! Thanks for reading! Just a reminder that I wrote this some years ago, and may have much more complicated feelings about this topic than I did when I wrote it. Happy to elaborate, feel free to reach out to me! 😄

Named after one of my favorite frogs.
🎵 The song for this post is Prince Fleaswallow's rap from Parappa the Rapper, by Masaya Matsuura 🎵
My most popular original tweet is from 2013:
Haskell holds me, a hysterical mess, crying and wailing over SML's body. "It should've been you!!" I yell, knowing it won't change anything.
— 💣 b∀BГO 💣 (@SrPablo) June 5, 2013
I really love playing with and thinking about programming languages.1 I often get asked which my favorite is, and while I struggle to answer, I often say that if I designed one, it'd look most like Standard ML.2 Even by Pablo standards, it's a dead language.
It was always a dodge that I avoided OCaml this long. That said, I'm happy to announce that this blog is now built on OCaml, after years of being built on Racket. I wrote a static site generator that still has plenty of holes, and while I don't recommend anyone else use it in its current state, I feel comfortable enough to build my site with it going forward.
If you see bugs in the site, please report them! 😅
What's great
Closing the correctness gap
All of engineering is an exercise in tradeoffs, and while you can have preferences, it's dangerous to let yourself believe they are Objectively Better. I'll state that my preferences are to maximize correctness when possible, and static types with strong guarantees are a great way to achieve this. While I love how fast I am when working in something like Python, Ruby, or JavaScript, my least favorite tasks in programming are
- writing tests with a ton of mocks
- debugging bad state
If you're familiar with OCaml, you'll know that these are tasks the languages greatly reduces. Your programs are a little harder to write, but much easier to maintain. You'll note my codebase, at this point in time, has no tests. This isn't ideal! Testing is great! But I'd never even conceive of writing other software this way in another language, because I wouldn't have confidence that the system I build would have its invariants preserved.
Closing the performance gap
If you spend enough time in dynamic, interpreted languages, you forget how fast computers really are. I didn't think I'd get to "launch" this project until I implemented a cache, much like Frog has, that determines what files have changed and only rebuilds the parts of the site as necessary. A clean build in Frog takes me about 16 seconds, and one from cache takes about 3.
When I first ran a complete build, my OCaml project built the entire site in less than a second. This is not a burn on Racket or Frog! They are amazing products by amazing people that I wholeheartedly admire! But there is a real joy in seeing optimized, compiled code work as quickly as it does.
I'm committed to continuing to try as much as I can in OCaml this year.
What's not great
Impacts of smaller community
This is undeniable: working in Python/Ruby/JavaScript/Java means almost every problem you can imagine has been solved by multiple other people. Your package managers just work. There are a million StackExchange answers on every permutation of tool connections.
When considering an OCaml library, my process was
-
Can I install this with OPAM? If not, I didn't include it: I really would prefer to stick to reproducible builds with a simple packaging mechanism.
-
How do I use this? I'd download it, look at its signatures in utop, and usually look at the source code itself (like this file in the Markdown parser, or this one in the ISO8601 date formatter). This is kind of the System Working As Designed, but it's a bit more exploratory than working in many other ecosystems.
Getting a working setup
There are several different ways to install OCaml's tools, and when you do install them you find that there are dozens, each individually handling a different part of the build chain. I misunderstood an instruction on the merlin install, so I was coding blind for a longer time than I would have liked.
In fairness, this is broken everywhere (though Haskell Platform and
Racket's single download are quite pleasant). Telling folks to download
nvm or rvm or virtualenv and how to pip install
or bundler install
or npm install
for these tools has a learning curve too. But they more-or-less
follow the same conventions, and per above, have a lot more resources online to
debug where they don't work.
OCaml/Reason split
OCaml is getting some new attention since Facebook released Reason, a comrade of OCaml, where you effectively write OCaml and it compiles down happily to JavaScript. It plays well with React.
While I think Reason and all the subsequent new attention is a good thing, it causes some angst over which to use, and exacerbates a lot of the above since it's yet another fragment in that ecosystem.
Resources
If you want to give it a try, I'd take a look at Real World OCaml, available online and very comprehensive.
When you need to look up a library, consider using the Jane Street OCaml Core library, or Batteries. I used Core since that's what Real World OCaml was using. You'll be Googling those docs a ton.
If you can, try to get Merlin set up, and work with a utop
instance nearby.
They'll really shorten your dev cycle.
1. ^ Previously, previously, previously, previously, previously, previously, previously, previously, previously.
2. ^ Dream language would have SML modules and types, Erlang-like VM and OTP, Lisp syntax. Such a combination is probably impossible and I'm probably missing a few other features, but those are a few of my favorite things.
Thanks for the read! Disagreed? Violent agreement!? Feel free to join my mailing list, drop me a line at , or leave a comment below! I'd love to hear from you 😄