Hacker News new | past | comments | ask | show | jobs | submit login

TL;DR: I championed the addition of OCaml to write web apps in our team and had I had the decision now I would've just used TypeScript because of the much better tooling, better interop and pretty much as competent type system + less build step headaches.

We use BuckleScript (without Reason, plain OCaml) to deliver a few web apps meant to run on mobile. The experience is decent and the lack of multicore support for OCaml doesn't really matter when you execute in JavaScript.

OCaml is mostly a fine language, but anyone familiar with a more ergonomic language like PureScript will miss a ton of features (higher-kinded types, type classes, etc.. People usually like to say you can make up for it with functors, but it's not really the same at all; much more cumbersome and less ergonomic. We do use functors a lot, but to say they're doing the same thing is being a bit too liberal, IMO). There's been a plan to implement ad-hoc polymorphism for many years now and honestly I don't think it'll see the light of day. Most things in OCaml move at glacial speed and I think it's better to look elsewhere in languages that already have these features if you're not already invested.

BuckleScript obviously adds JS interop on top and with time I've come to resent how it's done. It's pretty verbose, doesn't fit in with the rest of the language and is generally speaking pretty fiddly. PureScript has much better interop that looks exactly like the rest of the language, no ugly decorators needed.

Over time I've come to realize that even though I may want to use PureScript for projects, it's probably not going to happen with the small community and higher degree of investment needed for people. So while PureScript is superior to pretty much all "write something that runs in the browser" solutions right now, we're not very likely to use it (yet). BuckleScript is mostly the same and on top of that it's based on a worse language moving slower, with an interop layer that's worse.

With that in mind, the sanest way to do it is just to use TypeScript. It rates better in almost every metric that has to do with "Is this usable for us?". It lacks the niceties like HKTs, etc., but can pretty easily make up for most other features. I realized this after working on a talk about designing programs via the type system and being able to do most things with TypeScript that I'd expect to have to use PureScript/OCaml for. There are still parts missing, but those parts are missing in OCaml too and PureScript is the only one that gets abstraction completely right on a language level, barring dependent types.

There's a way to simulate HKTs via type defunctionalization which is applicable to both OCaml and TypeScript, so you can approximate it, and there's a library for it out in the wild called `fp-ts`.

With TypeScript, the interop story is obviously as good as you're going to get. With strict mode turned on (it is by default) it's not going to allow nonsense and in the past few years it's gotten features that allow you to do tons of type system modelling. I've already made strides in our code base to support things that we're doing in OCaml and to a large extent it's mostly the same kind of feeling of "It compiles, so it's very likely actually correct".

So all in all, since I discovered how to express more interesting type concepts in TypeScript (I was previously convinced, mostly by FUD, that this wasn't (yet) possible) I'd rather we don't add any more OCaml projects as I think the tradeoffs just aren't the right ones anymore: OCaml's (possible) advantages in the type system are few and they don't at all make up for the barrier to learning (even though OCaml is a very simple language), worse tooling or worse interop.

Edit: I should also add we've had a ton of odd issues with building our OCaml code via BuckleScript. Rollup, for example, plain didn't work at all even though there's no logical reason it should be failing. One of the base/prim files was failing to build and no one on either side could figure out why. We currently run webpack without a custom bs loader and precompile the .ml files instead. Installing the `bs-platform` package in our docker containers with `yarn` also failed for unknown reasons, so for docker we also precompile the entire `bs-platform` from source.




> With TypeScript, the interop story is obviously as good as you're going to get.

I would just like to add, yes at the immediate level you can trivially use JavaScript code in TypeScript, but when you are within the TypeScript world there are a few issues:

- You need typings for the JavaScript libraries you're using, which are fortunately abundant but you have to keep an eye on their quality, as lots of things can be typed as `any` or `function` which is effectively saying 'whatever'.

- The process of getting typings is not as uniform as you'd expect. For example, you want to use the Web and related APIs? They are behind a compiler flag, not an import: https://www.typescriptlang.org/docs/handbook/compiler-option... . In BuckleScript all available third-party APIs are done uniformly with imports or hand-written typings.

- You want to write typings for a module? You'll need a `.d.ts` file to contain them. In BuckleScript, JavaScript typings and your OCaml/Reason code are uniformly contained in implementation/interface files. There's no distinction.

Regarding the bundling, it's hard to tell exactly what that was, but generally your strategy of explicitly splitting up the compilation steps is a good one.

Regarding the Docker issues, that is unfortunate, I wonder if you have tried one of the pre-built BuckleScript images? E.g. https://hub.docker.com/r/andreysenov/bs-platform


Thanks for the detailed answer :). You talked very nicely about the dev front - can I also ask how the Said languages fared at runtime?


I have no basis for talking about this. My suspicion is that our OCaml apps perform pretty terribly if you look at raw numbers, because we use what is essentially a hobbyist library called `bucklescript-tea`[0], which implements the Elm Architecture. I can only assume it's not optimized. Fortunately, we don't need it to be. The README stresses that it's fast, but meh.

From reading, the Reason team have had great success using react from Reason (so OCaml) even without manual optimizations, because of immutable data (even compared to immutable.js). Take that nugget with a pinch of salt, though, because I didn't hear it recently and I'm not sure I ever saw real numbers behind it.

0 - https://github.com/OvermindDL1/bucklescript-tea




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: