First, is there comprehensive documentation available for utop
? I can’t seem to find any. I am using the CS3110 book (2.1. The OCaml Toplevel — OCaml Programming: Correct + Efficient + Beautiful) and information I glean from various blog posts such as opam - UTop: a much improved interface to the OCaml toplevel and Introduction to the OCaml Toplevel · OCaml Documentation.
I want to use a workflow like the #use "code.ml"
one described in the CS3110 book, but for more complex code that depends on a few libraries and multiple ppx. Currently if I #use
my .ml
files in utop
they bug out with various errors related to ppx processing and missing libraries.
I haven’t successfully figured out how to get utop
loading this code in a way that is all of these things:
- convenient (in the sense that the incantations required to load my code come from
dune
using at most one command) - functional (in the sense that the code loads at all)
- allows me to interact with the code as if I were in the unsealed module (in the way you can after using
#use
inutop
)
I have been able to load my module using dune
’s integration with utop
, but this seems to load the sealed module. For example, I can’t call functions that aren’t exported. This is inconvenient, because my goal is to interactively explore and debug the module.
Taking it down a level, I can reproduce my problem with a minimal test case, using instructions from Command-Line Interface — Dune documentation
$ dune init project --kind=l myproj
$ cd myproj
$ echo 'let i = 42' > lib/code.ml
$ dune build
Now, I’d like to use something like dune utop
to load this library such that entering i;;
into utop will print the value 42.
Following Command-Line Interface — Dune documentation I try:
$ dune lib
but…
utop # module S = Myproj;;
modle S = Myproj
…in other words, it looks like Myproj doesn’t export i
. I’ve also tried dune lib -- -implicit-bindings
but it makes no difference. The dune docs say -implicit-bindings
means there will “implicit bindings for toplevel expressions” but I’m not sure what that means.
The alternative also produces the same problem:
$ utop
utop # #use_output "dune ocaml top-module lib/code.ml";;
utop # i;;
Error: Unbound value i
utop # module S = Myproj;;
module S = Myproj
This makes sense to me. utop
is loading my module, but the module, having no .mli
, is apparently completely sealed.
Of course, with an example as simple as this, I can #use "code.ml"
in utop
. In my actual use case my dune file is non-trivial, and so the utop
setup is also non-trivial. For example:
(library
(name day07)
(inline_tests)
(libraries str)
(preprocess (pps ppx_jane ppx_deriving.show)))