OCaml as my primary language

90 nukifw 49 8/13/2025, 6:05:05 PM xvw.lol ↗

Comments (49)

noelwelsh · 16m ago
I saw a talk by someone from Google about their experiences using Rust in the Android team. Two points stuck out: they migrated many projects from Python, so performance can't have been that much of a concern, and in their surveys the features people liked most were basics like pattern matching and ADTs. My conclusion is that for a lot of tasks the benefit from Rust came from ML cicra 1990, not lifetimes etc. I feel if OCaml had got its act together around about 2010 with multicore and a few other annoyances[1] it could have been Rust. Unfortunately it fell into the gap between what academia could justify working on and what industry was willing to do.

[1]: Practically speaking, the 31-bit Ints are annoying if you're trying to do any bit bashing, but aesthetically the double semicolons are an abomination and irk me far more.

unstruktured · 9m ago
There is absolutely no reason to use double semicolons in practice. The only place you really should see it is when using the repl.
garbthetill · 4m ago
doesnt rust still have the advantage of having no gc? I dont like writing rust, but the selling point of being able to write performative code with memory safety guarantees has always stuck with me
benreesman · 6m ago
Came here to see if the top comment on an OCaml thread had something about Rust changing the subject to Rust with an oblique tieback to TFA.

Come on guys, this was old five years ago and its not organic, the strike force is quieter about brigading than it used to be, but you can still set your watch by it.

_mu · 1h ago
I haven't worked in OCaml but I have worked a bit in F# and found it to be a pleasant experience.

One thing I am wondering about in the age of LLMs is if we should all take a harder look at functional languages again. My thought is that if FP languages like OCaml / Haskell / etc. let us compress a lot of information into a small amount of text, then that's better for the context window.

Possibly we might be able to put much denser programs into the model and one-shot larger changes than is achievable in languages like Java / C# / Ruby / etc?

jappgar · 28m ago
That was my optimistic take before I started working on a large Haskell code base.

Aside from the obvious problem that there's not enough FP in the training corpus, it seems like terser languages don't work all that well with LLMs.

My guess is that verbosity actually helps the generation self-correct... if it predicts some "bad" tokens it can pivot more easily and still produce working code.

sshine · 5m ago
> terser languages don't work all that well with LLMs

I’d believe that, but I haven’t tried enough yet. It seems to be doing quite well with jq. I wonder how its APL fares.

When Claude generates Haskell code, I constantly want to reduce it. Doing that is a very mechanical process; I wonder if giving an agent a linter would give better results than overloading it all to the LLM.

sshine · 11m ago
> My thought is that if FP languages like OCaml / Haskell / etc. let us compress a lot of information into a small amount of text, then that's better for the context window.

Claude Code’s Haskell style is very verbose; if-then-elsey, lots of nested case-ofs, do-blocks at multiple levels of intension, very little naming things at top-level.

Given a sample of a simple API client, and a request to do the same but for another API, it did very well.

I concluded that I just have more opinions about Haskell than Java or Rust. If it doesn’t look nice, why even bother with Haskell.

I reckon that you could seed it with style examples that take up very little context space. Also, remind it to not enable language pragmas per file when they’re already in .cabal, and similar.

gf000 · 57m ago
My completely non-objective experiment of writing a simple CLI game in C++ and Haskell shows that the lines of code were indeed less in case of Haskell.. but the number of words were roughly the same, meaning the Haskell code just "wider" instead of "higher".

And then I didn't even make this "experiment" with Java or another managed, more imperative language which could have shed some weight due to not caring about manual memory management.

So not sure how much truth is in there - I think it differs based on the given program: some lend itself better for an imperative style, others prefer a more functional one.

esafak · 54m ago
I think LLMs benefit from training examples, static typing, and an LSP implementation more than terseness.
nextos · 22m ago
Exactly. My experience building a system that generates Dafny and Liquid Haskell is that you can get much further than with a language that is limited to dynamic or simple static types.
d4mi3n · 1h ago
I think this is putting the cart before the horse. Programs are generally harder to read than they are to write, so optimizing for concise output to benefit the tool at the potential expense of the human isn't a trade I'd personally make.

Granted, this may just be an argument for being more comfortable reading/writing code in a particular style, but even without the advantages of LLMs adoption of functional paradigms and tools has been a struggle.

nukifw · 1h ago
To be completely honest, I currently only use LLMs to assist me in writing documentation (and translating articles), but I know that other people are looking into it: https://anil.recoil.org/wiki?t=%23projects
nine_k · 6m ago
I wish somebody with this amount of experience would compare the benefits / shortcomings of using the ReasonML syntax. (The article mentions it once, in passing.)
ackfoobar · 1h ago
> Sum types: For example, Kotlin and Java (and de facto C#) use a construct associated with inheritance relations called sealing.

This has the benefit of giving you the ability to refer to a case as its own type.

> the expression of sums verbose and, in my view, harder to reason about.

You declare the sum type once, and use it many times. Slightly more verbose sum type declaration is worth it when it makes using the cases cleaner.

nukifw · 59m ago
In the specific case of OCaml, this is also possible using indexing and GADTs or polymorphic variants. But generally, referencing as its own type serves different purposes. From my point of view, distinguishing between sum branches often tends to result in code that is difficult to reason about and difficult to generalise due to concerns about variance and loss of type equality.
ackfoobar · 18m ago
Unless you reach an unsound part of the type system I don't see how. Could you provide an example?
wiseowise · 1h ago
> Slightly more verbose sum type declaration is worth it *when it makes using the cases cleaner.*

Correct. This is not the case when you talk about Java/Kotlin. Just ugliness and typical boilerplate heavy approach of JVM languages.

ackfoobar · 53m ago
> Just ugliness and typical boilerplate heavy approach of JVM languages.

I have provided a case how using inheritance to express sum types can help in the use site. You attacked without substantiating your claim.

wiseowise · 43m ago
Kotlin's/Java's implementation is just a poor man's implementation of very restricted set of real sum types. I have no idea what

> This has the benefit of giving you the ability to refer to a case as its own type.

means.

ackfoobar · 32m ago
> I have no idea

I can tell.

Thankfully the OCaml textbook has this explicitly called out.

https://dev.realworldocaml.org/variants.html#combining-recor...

> The main downside is the obvious one, which is that an inline record can’t be treated as its own free-standing object. And, as you can see below, OCaml will reject code that tries to do so.

wiseowise · 14m ago
That's for embedded records. You can have the same thing as Kotlin but with better syntax.
ackfoobar · 4m ago
If you don't do inline records you either

- create a separate record type, which is no less verbose than Java's approach

- use positional destructuring, which is bug prone for business logic.

gf000 · 56m ago
You mistyped "backwards compatible change" going back to close to 3 decades.
loxs · 35m ago
I migrated from OCaml to Rust around 2020, haven't looked back. Although Rust is quite a lot less elegant and has some unpleasant deficiencies (lambdas, closures, currying)... and I end up having to close one one eye sometimes and clone some large data-structure to make my life easier... But regardless, its huge ecosystem and great tooling allows me to build things comparatively so easily, that OCaml has no chance. As a bonus, the end result is seriously faster - I know because I rewrote one of my projects and for some time I had feature parity between the OCaml and Rust versions.

Nevertheless, I have fond memories of OCaml and a great amount of respect for the language design. Haven't checked on it since, probably should. I hope part of the problems have been solved.

ackfoobar · 13m ago
> the end result is seriously faster

Do you have a ballpark value of how much faster Rust is? Also I wonder if OxCaml will be roughly as fast with less effort.

shortrounddev2 · 1h ago
OCaml is a great language without great tooling. Desperately needs a good LSP implementation to run breakpoints and other debugging tools on VSCode or other LSP-aware IDEs. I know there ARE tools available but there isn't great support for them and they don't work well
debugnik · 30m ago
LSP isn't the protocol that interfaces with debuggers, that'd be DAP. You're right that OCaml debugging is kinda clunky at the moment.

OCaml does have an okay LSP implementation though, and it's getting better; certainly more stable than F#'s in my experience, since that comparison is coming up a lot in this comment section.

nukifw · 1h ago
Indeed, efforts should be made in terms of DAP (https://microsoft.github.io/debug-adapter-protocol//), extending the following experimentation: https://lambdafoo.com/posts/2024-03-25-ocaml-debugging-with-.... However, I find the assertion about tooling a bit exaggerated, don't you?
dismalaf · 1h ago
?? OCaml has had a completion engine for as long as I can remember (definitely over a decade) and it powers their LSP these days. I do know however that the community focuses mostly on Vim and Emacs.
FrustratedMonky · 32m ago
In F# comparison. Modules "my opinion, strongly justify preferring one over the other".

Strong stance on Modules. My ignorance, what do they do that provides that much benefit. ??

akkad33 · 1m ago
I don't know OCAML well but I think this is referring to the fact that modules on OCAML can be generic. In f# there is no HKTs that is types that can be parameterised with type classes. So in F# you have to have List.map, option.map etc, whereas in a language like OCAML or Haskell they would have one parametrised module
debugnik · 5m ago
[delayed]
raphinou · 1h ago
Some years ago I also wanted to make ocaml my primary language, but rapidly encountered problems: difficulty to install (on Linux due to the requirement of a very unusual tool which name and function I forgot), no response from community regarding how to solve that problem, no solid postgresql driver, ....

Wanting to use a functional language I pivoted to fsharp, which was not the expected choice for me as I use Linux exclusively. I have been happy with this choice, it has even become my preferred language. The biggest problem for me was the management of the fsharp community, the second class citizen position of fsharp in the DotNet ecosystem, and Microsoft's action screwing the goodwill of the dev community (eg hot reload episode). I feel this hampered the growth of the fsharp community.

I'm now starting to use rust, and the contrast on these points couldn't be bigger.

Edit: downvoters, caring to share why? I thought sharing my experience would have been appreciated. Would like to know why I was wrong.

johnisgood · 58m ago
> difficulty to install

Use opam: https://opam.ocaml.org or https://opam.ocaml.org/doc/Install.html.

Additionally, see: https://ocaml.org/install#linux_mac_bsd and https://ocaml.org/docs/set-up-editor.

It is easy to set up with Emacs, for example. VSCodium has OCaml extension as well.

All you need for the OCaml compiler is opam, it handles all the packages and the compiler.

For your project, use dune: https://dune.readthedocs.io/en/stable/quick-start.html.

Milpotel · 31m ago
"use opam" is always the answer but in reality its the worst package manager ever. I've never seen so many packages fail to install, so many broken dependencies and miscompilations that resulted in segfaults due to wrong dependencies. I just gave up with Ocaml due to the crappy ecosystem, although I could have lived with the other idiosyncrasies.
sestep · 9m ago
And even if you do get opam working for a project, it's not at all reproducible and will just randomly break at some point in the future. For instance, I had this in a Dockerfile for one project:

  RUN eval $(opam env) && opam install --yes dune=3.7.0
One day the build just randomly broke. Had to replace it with this:

  RUN eval $(opam env) && opam install --yes dune=3.19.1
Not a big change, but the fact that this happens at all is just another part of building with OCaml feeling like building on a foundation of sand. Modern languages have at least learned how to make things reproducible with e.g. lockfiles, but OCaml has not.
johnisgood · 6m ago
Use "opam lock" and "opam pin". Additionally, Dune's lockdir feature uses opam's solver internally to generate a lock directory containing ".opam.locked" files for every dependency. This is Dune's way of having fully reproducible builds without relying on opam's switch state alone.

Additionally, see: https://dune.readthedocs.io/en/stable/tutorials/dune-package....

nukifw · 29m ago
There is a lot of work on Dune Package Management that will fix some legacy issues related to OPAM, https://dune.readthedocs.io/en/stable/tutorials/dune-package... !! Stay tuned!
johnisgood · 10m ago
Dune is not a dependency manager, it is a build tool. Opam is the dependency manager. By default, Dune doesn't fetch dependencies, opam does that. That said, Dune does use opam, yeah.
nukifw · 4m ago
And the next milestone of Dune is to become an alternative package manager via Dune package Management, using a store in a "nixish" way.
johnisgood · 2m ago
I suppose it is still going to use opam internally, right?
johnisgood · 12m ago
I have never had issues and been writing OCaml and using opam for years.

Can you be more specific?

moi2388 · 1h ago
If I wanted to program in OCaml, id program in F# instead
nukifw · 1h ago
Hi! Thank you for your interest (and for potentially reading this).

Yes, F# is a very nice language, however, it seems to me that I am making a somewhat forced comparison between OCaml and F# in the following section: https://xvw.lol/en/articles/why-ocaml.html#ocaml-and-f

moi2388 · 57s ago
Thanks, that was an interesting read for sure!
Smaug123 · 52m ago
You can hack up GADTs in F# - for example, https://github.com/Smaug123/WoofWare.Incremental/blob/9b8181... (which uses https://github.com/G-Research/TypeEquality ). (The other missing features I agree are missing.)
nukifw · 49m ago
Yes, the trick is expanded here: https://libres.uncg.edu/ir/asu/f/Johann_Patricia_2008_Founda... (if you have `Eq a b = Refl : a a eq` you should be able to encode every useful GADTs. But having a compiler support is nice for specifics reason like being able to "try" to detect unreachable cases in match branches for examples.
debugnik · 35m ago
I've used equality witnesses in F# before, they kinda work but can't match proper GADTs. First you'll need identity conversion methods on the witness, because patterns can't introduce type equalities, then you'll realise you can't refute unreachable branches for the same reason, so you still need to use exceptions.
jimbob45 · 17m ago
It's always weird when Microsoft pulls an "embrace, extend, extinguish" but the "extinguish" part happens without their involvement or desire and then we're all stuck wondering how Microsoft got left holding the bag.