I have been working through this: Your First OCaml Program · OCaml Documentation
There is something very unclear here. This example works only if I create a file/module in lib/ with the same name as the project, in this case hello.ml. I can refer to functions from that module with Hello.function.
I would like to create mymodule.ml in lib and use a function from mymodule in bin/main.ml, but it fails Error: Unbound module. It seems very unintuitive, Mymodule.function should just work since the file exists in lib/ and files are automatically modules?
I have spent a bit of time trying to work this out, docs, gpt4+, etc. Nowhere is it at all clear to me anyway.
I am used to julia modules and scoping. I am here mainly to learn some more about types and functional programming, and because julia dose not do executables very well, I would like to build a tui. Of course there is rust, another time, and go, but I don’t like the feel of go, same for elixir too.
It’s because of namespacing. Dune wraps each library component in a toplevel module which has the same name as the library: Stanza Reference — Dune documentation
(wrapped <boolean>) specifies whether the library modules should be available only through the top-level library module, or if they should all be exposed at the top level. The default is
true, and it’s highly recommended to keep it this way. Because OCaml top-level modules must all be unique when linking an executables, polluting the top-level namespace will make your library unusable with other libraries if there is a module name clash. This option is only intended for libraries that manually prefix all their modules by the library name and to ease porting of existing projects to Dune.
In this case suppose you have
lib/ which contains:
Then the modules will be available as:
Thanks that makes sense.
bin/dune also needs to refer to lib with the same name, (libraries lib)
Then its all hunky dory.
In the tutorial setup
From that, there are two options:
- With a
lib/hello.ml file, as you found
- Without a
lib/hello.ml file, as described by @yawaramin.
However, you can expose other modules from the
lib folder (your
mymodule.ml) even in case 1. You need a
hello.ml file looking like this:
module Mymodule = Mymodule
let text = "hi"
You’ll be able to use:
Hello.text. If you write
module Foo = Mymodule, then
Hello.Mymodule.f becomes available as
Thanks, that is useful to know.
I think there is more to this than meets the eye.
The example at Your First OCaml Program · OCaml Documentation works fine using an ocaml 4.14.1 switch
However this exact same example does not work with an ocaml 5.1.1 switch
It fails with: Unbound value Hello.world
But it does work if you do what yawaramin says above.
That is edit lib/dune to
edit bin/dune to
refer to Lib.Hello.world in bin/main.ml
I am not sure if it is dune that has changed (likely) or the ocaml module system, but this example is broken for me using 5.1.1
Not ideal considering most beginners will just install the latest stable release. Probably just a right of passage.
Maybe this thread can help someone else, so thanks for the help.
I’m sorry to hear this is not working for you. There must be a difference between our setups.
I tested successfully minutes ago with ocaml 5.1.1 and dune 3.12.1. I’m using a freshly created
hello project using the steps described in the tutorial.
let () = Printf.printf "%s\n" Hello.world
let world = "Hello from a module"
hello folder, here is what I get:
$ dune exec hello
Hello from a module
I’m working on a tutorial addressing this topic, the draft is here: Modules and Libraries in Dune · OCaml Documentation
It’s no big worry. Learning.
I went through it all again using 5.1.1 and it worked fine. I did have an unbound module error in my editor (hx), but dune exec worked and after compile the unbound module warning went away.
Thank you for your time, I am enjoying learning about ocaml modules.
Happy to hear it works. Have you spotted what went wrong initially? I’m concerned the tutorial text may not be clear enough or misleading. I’d like other learners avoid falling into the same pitfalls.
Apologies. I have been away somewhere with no internet.
I am not sure, sometimes it is just getting used to new things.
Interested to see there is a new tui package released called MintTea based on the elm architecture. I was not finding the examples in the nottui repo terribly easy to understand, though last I tried they were compiling and working fine.
The documentation on the ocaml site is really great, keep up the good work. It is a nice clean language which I love, languages with lots of brackets get very ugly at times.