Setting up a new OCaml environment in 2026 is not yet a fluid experience

Thanks for your feedback.

As I said, with Win11, I decided not to use a VM or a container and just use minimum, which should be WSL (or maybe Cygwin ?).

Dev container (based on Docker) appears to be very interesting because VS code appears to be designed for that. See:
https://code.visualstudio.com/docs/devcontainers/containers
https://code.visualstudio.com/docs/devcontainers/tutorial

According to your container experience on Win, are these 2 resources I just found enough?

Docker desktop on Win11 also requires WSL.
My PC (recent, with Win11 up to date) is still blocked with “WSL is too old”. After a bunch of readings, I’ve not yet found a solution.

From you experience, in order to get Docker and Dev Containers, how to get a clean up&running WSL environment with Win11? Can you highlight key points (check/install/repair… or whatever)?

Have you tried to install OCaml natively on Windows (with winget opam…)?
https://ocaml.org/install#windows

REPLs are a trap for most beginners, not a feature. REPLs have odd semantics, require you to load strange libraries, give you module and path errors, etc. And OCaml’s REPL is particularly quirky (I would argue that only Python’s is worse). Making beginners deal with complications in order to support a REPL that they’re never going to use is a bad choice.

Everything REPL should disappear from the beginner website and “Your First OCaml Program” should be the standard pathway. That’s the path that practically every modern programmer coming from Node, Cargo, etc. are familiar with.

And figure out how to get rid of “switches” from newbie documentation. It’s unreasonable for beginners to have to figure out a concept that basically doesn’t exist anywhere else. And yet OCaml takes a shovel and smacks newbies right in the nose with it.

Also, I have to concur that putting a source file in “/bin” is going to confuse newbies. Don’t do that. Put stuff in “/src” or at the top-level like everybody else in the universe. Old-school greybeards can change their configuration to “/bin” if they want and everybody else can just get on with life.

3 Likes

I’ve tried to install OCaml with WSL2.
I’ve been stuck with wsl.
Win11 pro : Hyper-V, WSL, VM Platform, Wind Hypervisor Platform are enabled.
I’ve tried many things, so I don’t know before I start from scratch.
Installing VSL with the admin account may have unlock something in my normal user account where elevated permissions were required but not given while PS was running as administrator (even in GUI mode).
With PowerShell, it seems wsl doesn’t work while wsl.exedoes…
It’s the same for winget : winget doesn’t work andwinget.exe works…
With Terminal, wsl and winget works.

Well. After some hours, I have opam and ocaml installed via VSL (Debian).

To update the current shell environment, run: (& opam env) -split ‘\r?\n’ | ForEach-Object { Invoke-Expression $_ }

or (https://ocaml.org/docs/ocaml-on-windows):

On CMD:

> for /f "tokens=*" %i in ('opam env --switch=default') do @%i

On PowerShell:

> (& opam env --switch=default) -split '\\r?\\n' | ForEach-Object { Invoke-Expression $_ }

eval $(opam env) seems much friendly !

In Win, how do you configure automatic env setup ?

With linux, say debian, a command (a hook) is added in personal config file (~/.bashrc). Each time you launch a shell, your env is updated with the current/selected opam “switch”.

With Docker, which image can you recommend?

only Python’s is worse

Python’s is slightly better for exposing docstrings. For example, help(print). That it doesn’t have tab completion is a pain but, like Ruby, what it does have comes as values in the language: you can dir(““) and then, if that list of words is tedious to visually scan through, process the array first:

>>> [x for x in dir('') if x.startswith('is')]
['isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper']

One of the applications I use comes with its own batteries-removed installation of Python and interactively interrogating it was very useful for finding out what I could get it to do.

One of the first things a beginner will notice about OCaml is that you can’t just throw a dbg!(x) to see what x looks like in part of your program, but a REPL comes with default printers and you can do something like Hashtbl.to_seq cache |> List.of_seqto get a quick look where you still don’t have one. Merlin or an LSP are better for quickly and interactively looking up functions since it has docs and jump-to-source available, but I still often open utop just to type in the name of a function and get a hint from its type.

Node has a REPL.

get rid of switches

Switches also reduce friction over a longer time-horizon, and are an easy alternative to fussing with package conflicts. Want to use OCanren which requires OCaml <4.13? You don’t have to choose between it and your other OCaml 5.x work, you can just have a switch for it. This sort of thing isn’t unique to opam. There’s https://rvm.io/ for Ruby, GitHub - taylor/kiex: Elixir version manager for Erlang.

You save a lot of time later for the small upfront cost of not really having to think about it when following a guide to set up OCaml. My first impulse when I saw your post was to make a joke about how you should run with your ideas and use a horse mascot, since you’re designing a simpler version a camel, but a horse is also appropriate because horses have blinders to not be startled by mere exposure to things like switches or bin/

I don’t have a strong opinion on the bin/ convention, but here’s an example Rust program tree that has a src/bin directory:

├── Cargo.lock
├── Cargo.toml
├── src/
│   ├── lib.rs
│   ├── main.rs
│   └── bin/
│       ├── named-executable.rs
│       ├── another-executable.rs
│       └── multi-file-executable/
│           ├── main.rs
│           └── some_module.rs

From Package Layout - The Cargo Book

Here are two examples in the wild:

There’s a lot of actionable feedback in this thread (many relating to friction points folks have been working on for awhile and are still working on, some probably relatively novel). IMO, the debate on directory names is not too productive tho.

2 Likes

Depends on what you are after, but ocaml/opam - Docker Image has a lot of images that are published regularly as part of the community infrastructure.

And they are a spectacular way to confuse new users who followed some advice, activated some switch, and now suddenly a bunch of their programs aren’t working. (Been there, done that, took me far too long to figure out).

You have to let beginners meet Ocaml via a path from using their previous knowledge which is not OCaml. This is especially true for things relative to the OCaml ecosystem which, I’ll be blunt, generally ranges somewhere between actively unhelpful to disastrously confusing.

My first impulse when I saw your post was to make a joke about how you should run with your ideas and use a horse mascot, since you’re designing a simpler version a camel, but a horse is also appropriate because horses have blinders to not be startled by mere exposure to things like switches or bin/

Oh, please, I’ve traded flames with Erik Naggum back on Usenet. You need to try a lot harder before I break out the asbestos underwear, junior.

1 Like

There’s certainly an ideal at which everything is already familiar, somehow, despite the “previous knowledge” also differing as people come from different camps, and opposite it an imaginable extreme where everything is completely unfamiliar, but the thread has a lot of complaints about difficulties that are either overcome immediately like confusion about bin/, or upon just asking anyone, even AI:

A poster followed some OCaml guide and now most of his OCaml programs don’t seem to exist anymore. Speculate on what happened.

The reply starts:

The most plausible explanation is an opam switch mishap.

This level of difficulty is really not unusual and every other language something like it. Personally I noticed this the most with Java, not a niche language.

1 Like

Those Rust projects are a bit odd. Let’s look at the top Rust crates by downloads.

syn–src no bin. bitflags–src no bin. I have to go the whole way down to cc-rs before I hit a bin in src. So, like 1 in 40 or so crates? Definitely not the common case.

However, those are a lot of libraries. Let’s look at the command line tools and see if Rust conflates the two.

Ripgrep–src separate with exe into /target. fd–same. bat–There’s a bin. Let’s compile it up. Nope. exe into /target. I can go on.

Even if there is a /bin directory underneath /src, it only holds source code and is read only. Compiled executables go over into /target.

Sure, /bin in OCaml with source code and executables is not a showstopper. But it’s yet another papercut.

And the point isn’t the name. It isn’t relevant whether it’s /bin, /target, or /gargle. The point is not having source code and executables being conflated together.

The fact that even AI flat out calls it a mishap should be waving giant red flags, you know.

You can tell every newbie to wear oven mitts because the pot handle gets too hot. Or you can design the pot handle to not get hot under most circumstances so that newbies don’t need the oven mitts most of the time.

For me, OCaml, the language, never slowed me down much at all. However, I’m always tripping over ecosystem weirdnesses.

And, personally, I would argue that the ecosystem stuff is more important than the language proper nowadays. For example–part of why Zig is gaining so much traction is because it makes interfacing with C libraries very straightforward (even to the point of being willing to rip out the native build system and replace it with Zig–see All Your Codebase · GitHub). Gleam and Elixir similarly because you get access to the Erlang/BEAM OTP ecosystem without the Erlang Prolog weirdness. etc.

OCaml has lots of good stuff (one Haskeller commented that OCaml is the only language that gets modules right, for example), but the paper cuts make it very hard to get to it all.

It’s true that REPLs can be misleading. But all my students, every year, love using the REPL with dune utop, in fact so much that they’re better at that than compiling binaries (to my despair). I personally think one of the strengths of functional programming is the ability to resort to an interpreter (thanks to the “straightforward” operational semantics of such languages), in particular when developing (to test ideas, to glue some unfinished parts of the code…).

On a more general note, I do agree that -even on Linux- setting up an OCaml working environment is still not a breeze for students (nor for myself: I still have to reach for older projects or the documentation to set up basic things such as ocamlformat, VSCode, tests and non-fatal warnings…).

2 Likes

Some time ago, I wrote a tutorial for OCaml beginners. I mentioned the existence of a REPL, but quickly moved to compiling .ml files, deliberately avoiding dune at first and instead using makefiles and the traditional compiler toolchain.

Later, when teaching Python, I noticed that true beginners learn basic syntax faster when starting with a REPL, since they can focus on one aspect at a time and get immediate feedback. Only later they appreciate writing programs outside the REPL. So, I don’t see any harm in mention utop in tutorial for a first exploration of OCaml syntax, that probably many beginners coming from R or Python could appreciate.

Regarding the bin/ directory, I don’t think this debate is productive. Beginners quickly understand that bin/ is for code (clearly said in tutorial), and experienced programmers will infer its purpose immediately after running dune init proj with ls bin/. Moreover, dune is completely agnostic about directory names, so users are free to organize projects as they wish.

2 Likes

Yes, switches is an advanced topic and a beginner can use the default switch for a while.

But switches also exist in Php, Python, Ruby, Rust, Ada too. And much more. (But with other names and are created with the phpenv, pyenv, rbenv, rustup, alr commands). Many toolchains have a way to handle multiple sets of compilers and libraries.

About beginners, one of the first read page is probably Your First OCaml Program · OCaml Documentation… The bin directory convention is quite clear.

6 Likes

Context: Win11.
Let’s assume I’m a beginner in setting up an OCaml IDE (while not a beginner in OCaml). And an ordinary or new user of Docker desktop (while experienced with cli docker on debian).

Here’s a snapshot of images I’m proposed:

Which one should I choose? According to which criteria?
It reminds me (Sun) Java website proposing various version of jre or/and jdk, only raising questions instead of giving answers.

Well, I’m mainly using debian as linux distro, and I’m trying to use Win.
I already know that opam2 is (or should be) better.
I already know that some ocaml packages are working only with ocaml <=5.2 …
I don’t know if ocaml 5.5 a good choice for beginning.
I don’t know opam, so I’m not supposed to know that I can create a “switch” with any ocaml compiler.

Remember that we are talking about someone who just want to learn OCaml and doesn’t want to be a docker, wsl, linux, win… expert yet.

Conclusion:
Just for an OCaml docker image, there are too many choices, while one pointer to a single recommended docker image is enough (image continuously updated).
A very very limited number of options may be proposed, such as “ubuntu or debian or alpine” if it’s presented as NOT necessary but a pure option (say, not to upset a debian user because of ubuntu).

This is just about using docker on Win. Keep in mind that our “client” must also understand opam, ocaml, ocamlc/ocamlopt, a build system (possibly dune), set up his editor…

This is the point. And a very good indicator.
And you are a professor in FP/OCaml, so we can rely on your feedback.

Each time I came back to OCaml I’ve experienced that personally, and I’ve seen many other people having the same experience.
This is repellent (with no play on words!). But people who are using OCaml every day can’t see or understand that, as their environment works well, and as they accepted to put the source of their core program in a dune directory despite it’s weirdly named bin/ … (again, dune internals are not criticized as it builds as expected).

I’m not using OCaml every day. I picked it back up only a month ago and went through this whole process from scratch, and still mostly work in other languages. I believe you that you found bin/ confusing for a moment or two, and like I said I encountered much of what you opened the thread with. Trying to format a file and instead getting a complaint about missing .ocamlformat, adding a dependency and starting to write code for it but having no completions yet, this is real friction that persists even after you think about it and then get over some confusion.

What I don’t believe at all is that the following thought, in someone considering OCaml, even rises to the level of a papercut: “Oh, bin? Does it contain binaries? Ah, no, it contains source for binaries." Paper cuts don’t heal even this fast. It’s also neither an achievable goal nor a worthy goal to try to ensure that nobody approaching OCaml will ever encounter anything to ask a question about or think about. There’s very little point in clearing a few fallen leaves out of the path of a traveller who is both coming from and heading towards a thick jungle. And when a problem is below the level of a papercut, there’s also a very low threshold at which any solution causes worse problems than it solves. For example, even talking about this problem has consumed more time than anyone has ever or will ever lose to the problem itself.

7 Likes

Dune is close to releasing package management now…you won’t need to care about switches any more. You can help test it out: https://nightly.dune.build/

2 Likes

I must add that the bin convention is not a problem for students since they usually don’t have enough experience to think that it usually corresponds to a directory holding binaries. I don’t think this issue is a big deal, every language or environment comes with its share of surprising choices; as long as they’re well-explained, we can deal with it. I mean, there are far far worse “paper cuts” when developing than having a source directory named bin (BTW dune init could use another name since it’s only a convention).

Like I said before, IMO, the biggest issue is rather that:

  • it’s not yet possible to “just” start developing (meaning having ocamlformat, emacs/vim/lsp configured…) with a couple of short one-liners
  • the so-called “opinionated” choices of dune and dune profiles are hard or impossible to escape (when it’s possible, it’s through options not easy to explain to students).

I have discussed these issues a few times these last years and the situation has barely evolved (an issue about the slowness of dune utop was addressed, but only several months later, once @gasche entered the discussion).

dune is clearly more aimed at experienced OCaml developers than at students (even though students are probably the largest pool of OCaml users and today’s students may be tomorrow’s developers).

I don’t think that’s a huge deal but a sum of small issues is still annoying.

1 Like

Hi @Luc_ML,
If I may, I feel that you’re not acting in good faith and that your tone is a bit assertive. You may not share the vision, experience, or needs of other people, and even if everyone is opinionated in their own ways, in my experience tooling developers and documentation writers in the OCaml community work hard to accommodate for all use-cases. The beginner experience has also greatly improved in the past decade. I think you’ve encountered a few setbacks (and I empathize with you!) and now you’re sharing a bit of frustration and hostility.

I was part of the team that created the Docker images, so I may be a bit biased, but when I follow the link that @shonfeder shared, I very clearly get the following note:

The following repositories are no longer updated: ocaml/opam2, ocaml/opam2-staging, ocurrent/opam and ocaml/ocaml. To get the latest and greatest images use this repository (ocaml/opam).

when I follow a link to any of the deprecated repositories, I get:

Deprecated. Use ocaml/opam - Docker Image instead.

We needed to keep these repositories around for compatibility, but it could be possible to remove them now that quite some time has elapsed.

Just for an OCaml docker image, there are too many choices, while one pointer to a single recommended docker image is enough (image continuously updated).
A very very limited number of options may be proposed, such as “ubuntu or debian or alpine” if it’s presented as NOT necessary but a pure option (say, not to upset a debian user because of ubuntu).

I beg to differ, your use-case is not the same as everyone else’s. The images cover a wide range of systems (Linux distributions, macOS, *BSD, Windows), on many architectures (amd64, aarch64, risc-v, x86, power). This helps asserting correctness and portability of OCaml packages, and has been an invaluable tool in improving the ecosystem. For instance, I was able to debug a packaging issue of an old version of Merlin for OCaml 4.07-4.13 a few weeks ago by simply spawning one of these images.
Note that there is indeed a pointer to a recommended Docker image:

The latest tag is the latest release of OCaml running on the latest version of Debian (Debian is used as it has the widest architecture support for OCaml).

The Windows experience with OCaml was notoriously a difficult one, but it has immensely improved. As mentioned, winget install opam really is enough to have a working installation of OCaml on Windows. I fear that you’re putting too much weight on the OCaml tooling when you’re also complaining about the limitations of the external tools. Note that there are also OCaml Docker images for Windows.

In Win, how do you configure automatic env setup ?

You’re looking for how to set up a profile for your shell. After a bit of search, It seems hard to achieve with cmd but doable with PowerShell.

You’re complaining about the default structure of OCaml projects. I did share the skepticism at first, but I’ve encountered a few projects distributing executable and libraries in the same repository, and I’ve learned to appreciate the separation of lib/ and bin/ directories. The default structure doesn’t matter much once the project grows in complexity. As mentioned, you can always rename these files, the proposed naming is arbitrary.

Cheers.

3 Likes

Are you referring to the default set of warnings Dune enables? Note that starting in 3.21 Dune will use the same set of warnings as the compiler by default (see https://github.com/ocaml/dune/pull/12766).

Cheers,
Nicolas

2 Likes