The historical way is to have a .ml and a .mli files. The .ml file contains the implementation. Any documentation in that file is considered implementation detail, will not be published by ocamldoc. The .mli file contains everything users need to know, including documentation, function signatures, etc.
Interestingly, the .mli and the .ml signatures do not necessarily need to agree. For instance, a global variable in the .ml does not need to be published in the .mli. More interestingly, a generic function in the .ml does not need to be exposed as generic in the .mli, or can have more restrictions.
You could easily emulate this in Rust, but it's not the standard.
The historical way is to have a .ml and a .mli files. The .ml file contains the implementation. Any documentation in that file is considered implementation detail, will not be published by ocamldoc. The .mli file contains everything users need to know, including documentation, function signatures, etc.
Interestingly, the .mli and the .ml signatures do not necessarily need to agree. For instance, a global variable in the .ml does not need to be published in the .mli. More interestingly, a generic function in the .ml does not need to be exposed as generic in the .mli, or can have more restrictions.
You could easily emulate this in Rust, but it's not the standard.