I have a module MyMonad
that provides a bind function as (let*)
operator, but also as >>=
operator for old-style code.
The idea is that old code can use it as:
let foobar () =
let open MyMonad in
foo "test" >>= fun s ->
bar s 1 >>= fun (a, b) ->
return a + b
and that new code compiled on OCaml >= 4.08 can use it as:
let foobar () =
let open MyMonad in
let* s = foo "test" in
let* a, b = bar s 1 in
return a + b
Inside the module MyMonad.ml
, these operators are implemented in a straight forward way:
let (>>=) a f =
...
let (let*) = (>>=)
However, on OCaml <= 4.07, the last line is a syntax error. And the same is true for the val (let*) : ...
line in the MyMonad.mli
interface file.
This issue occurs especially when this module is meant to be used in BuckleScript (nowadays ReScript) as well, which is based on OCaml 4.06 and where it is not clear when they will upgrade to a later OCaml version.
How can I mark those last lines to be compiled only on OCaml >= 4.08?
Note: I'm aware that I could create two modules, one adding (let*)
on top of the other and being excluded on old compilers. But I wonder if there is a more elegant solution.
To answer this question myself, there is indeed to need to stick with >>=
, the new syntax can be used via shims with old OCaml compilers and even BuckleScript (nowadays ReScript).
The latter can be achieved as follows:
Create a new OPAM switch into the current directory for the 4.06 OCaml compiler. This is the version on which is the current BuckleScript version is based, and it is needed to convince the shims to actually do something (for more recent compiler versions those would compile to a no-op):
opam switch create -wy --no-install . 4.06.0
Install the ocaml-syntax-shims
OPAM package:
opam install -wy ocaml-syntax-shims
Add the following preprocessing line to you bsconfig.json
configuration file:
{
"pp-flags": "./_opam/bin/ocaml-syntax-shims -dump-ast",
...
}