And we have another record with the same record’s element name in the bin/main.ml :
open Core
type cinfo = {
name: string
}
let () =
let ci = {name = "ok"} in
print_endline ci.name
let () =
let ki : Klib.kinfo = { name = "hello"} in
print_endline ki.name
$ dune build
File "bin/main.ml", line 13, characters 22-39:
13 | let ki : Klib.kinfo = { name = "hello"} in
^^^^^^^^^^^^^^^^^
Error: This expression has type cinfo but an expression was expected of type
Klib.kinfo
The type annotation that you added (let ki : Klib.kinfo = ...) is enough for the compiler to disambiguate and pick up the correct type in this case. The reason it’s not doing so in this case is that lib/klib.mli is exposing the kinfo type as an abstract type so bin/main.ml can’t see its internals and construct an instance of it.
Adding the type definition to lib/klib.mli should solve it. lib/klib.mli should be
I was curious that if it is appropriate to export a record type?
In simple this case, we are good to modify both the klib.ml and klib.mli at the same. But in real world, we might have more than 10 fields inside a record, and it might easy prone to bugs in that case.
Hi, you won’t have bugs because the compiler will force the type declarations to match in both files.
But you will break the code of users if you update the record type.
Instead you could expose the type as abstract, and provide constructors and deconstructors, which could be less prone to breaking.