I currently have two "layers" of modules that represent identifier-data relationships in a database.
The first layer defines identifier types, such as IdUser.t
or IdPost.t
while the second layer defines data types such as User.t
or Post.t
. I need all the modules of the first layer to be compiled before the modules of the second layer, because a Post.t
must hold the IdUser.t
of its author and the User.t
holds the IdPost.t
of the last five posts he visited.
Right now, IdUser.t
provides functionality that should only ever be used by User.t
, such as the ability to transform an IdUser.t
into an IdUser.current
: for security reasons, this transform must only ever be performed by the function User.check_password
. Since IdUser
and User
are independent modules, I need to define those features as public functions and rely on conventions to avoid calling them anywhere outside of User
, which is rather dirty. A symmetrical situation happens in IdPost.mine
:
module IdUser : sig
type t
type current
val current_of_t : t -> current (* <--- Should not be public! *)
end = struct
type t = string
type current = string
let current_of_t x = x
end
module IdPost : sig
type t
type mine
val mine_of_t : t -> mine (* <--- Should not be public! *)
end = struct
type t = string
type mine = string
let mine_of_t x = x
end
module Post : sig
(* Should not "see" IdUser.current_of_t but needs IdPost.mine_of_t *)
val is_mine : IdUser.current -> IdPost.t -> IdPost.mine
end
module User : sig
(* Should not "see" IdPost.mine_of_t but needs IdUser.current_of_t *)
val check_password : IdUser.t -> password:string -> IdUser.current
end
Is there a way of defining an current_of_t : t -> current
function in IdUser
that can only be called from within module User
?
EDIT: this was a simplified example of one pair of modules, but there's an obvious solution for a single pair that cannot be generalized to multiple pairs and I need to solve this for multiple pairs — about 18 pairs, actually... So, I've extended it to be an example of two pairs.