Using Modules (15 characters long now)

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.

Regards
David

1 Like

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:

dune
mymodule.ml
othermodule.ml

And dune contains:

(library
  (name lib))

Then the modules will be available as: Lib.Mymodule and Lib.Othermodule.

Thanks that makes sense.

bin/dune also needs to refer to lib with the same name, (libraries lib)

Then its all hunky dory.

Regards
David

1 Like

In the tutorial setup lib/dune contains:

(library
 (name hello))

From that, there are two options:

  1. With a lib/hello.ml file, as you found
  2. 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.Mymodule.f and Hello.text. If you write module Foo = Mymodule, then Hello.Mymodule.f becomes available as Hello.Foo.f

Thanks, that is useful to know.

Regards
David

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
(library
(name lib))

edit bin/dune to
(executable
(public_name hello)
(name main)
(libraries lib))

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.

Kindness
David

1 Like

Thanks David,

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.

bin/dune

(executable
 (public_name hello)
 (name main)
 (libraries hello))

bin/main.ml

 let () = Printf.printf "%s\n" Hello.world

lib/dune

(library
 (name hello))

lib/hello.ml

let world = "Hello from a module"

From the hello folder, here is what I get:

$ dune exec hello
Hello from a module                

P.S.

I’m working on a tutorial addressing this topic, the draft is here: Modules and Libraries in Dune · OCaml Documentation

2 Likes

It’s no big worry. Learning.

Thanks
D

1 Like

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.

Kindness
David

3 Likes

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.

Kindness
David

2 Likes