How can types be exposed from a module without needing to reference from the module level?

I am wondering how the name of a type can be exposed from a module, without needing to reference it from the module level. For example, in the standard library there is a type for a list, within the module List, but when writing code using the standard library one can simply write functions with type annotations of 'a list. Without needing to use 'a List.list or 'a List.t or something like that.

The list type is defined in the OCaml core library (not to be confused with Jane Street’s Core library, despite the unfortunate name clash): OCaml - The core library

type 'a list = [] | :: of 'a * 'a list

The members defined in the core library are built-ins, i.e. they are always available in every OCaml program. There are a couple of ways to get a similar effect:

  • Use the open Mod syntax to open the module Mod in a large-enough scope so that its members are available from that point onwards in the file
  • Use your build system’s ‘auto open’ functionality to have some modules automatically opened without having to explicitly open them.

However, these practices are best avoided as much as possible, because opening lots of modules in scope leads to confusion about where items are coming from, and has a negative impact on readability of the code. It’s rather easier to tell where Mod.t is coming from, than where mod is coming from.

I generally agree with not opening lots of modules for readability. It can sometimes be helpful to expose a small number of things.

Thank you very much for your answer. It was very helpful.

Do you know of a way to not include core when compiling, similarly to how -nopervasives excludes the Stdlib?

I believe this is not possible at the moment.

Cheers,
Nicolas

1 Like

It is not possible at all. You cannot remove core types without removing core features of the language. For instance, float literals relies on the existence of the float type or optional arguments depend on the option type.

2 Likes

On the other hand, you can hide a core type by reusing its name (although obviously this is an ugly thing to do ) : typing type list = unit at the beginning of your code will force you to write List.t rather than list in your type annotations (which seems to be the asker’s original intent). Once your code is finished, you can remove the ugly prelude.

Sadly(?) this doesn’t force pretty-printing to use List.t. Try that in utop (OCaml 4.12):

# type list = |
type list = |
# [0]
- : int list/2 = [0]
# ([0] : _ List.t)
- : int list/2 = List.(::) (0, [])