Why is my own (implicit) module unbound?


There’s something I don’t understand with (implicit) modules, compilation (dune), cma and the toplevel.
In Lib/i201.ml, I’ve put this simple type definition:

type nombre = E of int
            | R of float
            | C of float*float

Then, thanks to this dune file:

  (public_name inf201)
  (name        i201)

I can build my library inf201 successfully.
In the Lib/_build/default directory, I try to load it in a toplevel:

default § ocaml i201.cma 
        OCaml version 4.06.1

Findlib has been successfully loaded.../...

# I201.E 1 ;;
Error: Unbound module I201

Same problem with #load:

default § ocaml
        OCaml version 4.06.1

Findlib has been successfully loaded.../...

# #load "i201.cma" ;;
# I201.E 1 ;;
Error: Unbound module I201

I guess there’s something obvious I’ve missed.

1 Like

It seems that the cmi file is not visible from the toplevel. Rather than struggle with finding the right file, you can use dune utop Lib to launch utop with your library already loaded.

Thanks for your reply. Indeed, dune utop works as expected:

default § dune utop
Entering directory '/.../Lib'
        │ Welcome to utop version 2.2.0 (using OCaml version 4.06.1)! │         

utop # I201.E 1 ;;
- : I201.nombre = I201.E 1

But the library I intend to develop will be used in a scholar environment where utop won’t be available.
I wonder if this problem has to do with the absence of .mli and/or explicit module definition.

Your problem mostly comes from trying to use an uninstalled library. It seems fine to use utop for your own test. If you want to test in the student environment, you could pin the library with opam. Or a more manual solution would be to use dune build -p inf201 and then use the file to be installed in _build/install.

The way ocaml works, there are two sets of files: the code, and the “module descriptions”. Both need to be present for the toplevel to work. As others have pointed out, dune utop will take care of loading them. But there are a number of mechanisms. There’s the toplevel’s source-path directive ("#directory"): you can give the directory containing the CMI files you wish to have available. You can also package your code and install it via findlib, and then use the findlib topfind/require directives,e.g.

#use "topfind";;
#require "utils" ;;


I think the #directory mechanism is the most basic; all the others (I suspect) build on top of that (written by different people/groups at different times).

I was thinking about this: Have you thought-thru your environmental assumptions? I’ve been building caml-light/ocaml setups for … decades, and the “opam” way of doing it is hands-down the simplest I’ve seen. If you’re able to pre-req opam, then, well, “dune utop” is as easy to install as anything else.