I had come to the same conclusion. On Aug 6, 2014 8:14 AM, "Trevor Smith" wrote: > Hello, > > I have a question about using .mli files for increased readability. I > think my question boils down to: "Can one tersely add type constraints to a > signature defined in a .mli in that same .mli file?" > > Detailed problem: You want to have a read interface and a write interface > for the same implementation. > > We'll use a trivial example with a character and a name. > > module type CharacterSig = sig > val t > val create : string -> t > val name : t -> string > end > > module type MutableCharacterSig = sig > val t > val create : string -> t > val name : t -> string > val set_name : t -> string -> unit > end > > module CharacterImpl = struct > type t = {name : string ref} > let create name = > {name = ref name } > let name c = !(c.name) > let set_name c name = > c.name := name > end > > module Character = (CharacterImpl : CharacterSig with type t = > CharacterImpl.t) > module MutableCharacter = (CharacterImpl : MutableCharacterSig with type t > = CharacterImpl.t) > > But what I would like is to specify the read and write signatures in .mli > files for a more readable codebase. > > So: > > character.mli: > val t > val create : string -> t > val name : t -> string > > mCharacter.mli: > val t > val create : string -> t > val name : t -> string > val set_name : t -> string -> unit > > characterImpl.ml (* ... implementation as above ... *) > > However, it is not clear to me that there is a way to attach the type > constraint to character.mli and mCharacter.mli, while keeping the terse > readability of the .mli file. One idea for a solution, would be to > reference a "this" so that the interface could show that it was being > implemented by CharacterImpl, and include the type constraint. > > The solution I've come to use, that is still pretty readable, is to define > the signature in the .ml file (so no .mli file) and then defining an > internal module which I include (so that I can still reference file name as > the module). So: > > character.ml > > module type CharacterSig = sig > type t > val create : string -> t > val name : t -> string > end > > module T = (CharacterImpl : CharacterSig with type t = CharacterImpl.t) > include T > > However, it seems like there could be a slightly more readable way of > doing this. > > Thoughts? Thank you. > > Trevor >