From: "Török Edwin" <edwin+ml-ocaml@etorok.net>
To: caml-list@inria.fr
Subject: Re: [Caml-list] Type Constraints and .mli
Date: Wed, 06 Aug 2014 18:36:54 +0300 [thread overview]
Message-ID: <53E24B96.8080402@etorok.net> (raw)
In-Reply-To: <CAG-KTt_4CUmxmpoww-5aAR_4o5WH7hq_Dah1ENrHzA1ZHq4ogA@mail.gmail.com>
On 08/06/2014 03:14 PM, 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 <http://c.name/>)
> let set_name c name =
> c.name <http://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
shouldn't this be a type?
> 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.
Not sure I understood exactly what you want to do, but using 'include module type of' and 'type t = CharacterImpl.t' should work:
character.mli
type t = CharacterImpl.t
val create : string -> t
val name : t -> string
character.ml:
include CharacterImpl
mCharacter.mli:
include module type of Character
val set_name : t -> string -> unit
mCharacter.ml:
include CharacterImpl
characterImpl.ml:
type t = {name : string ref}
let create name =
{name = ref name }
let name c = !(c.name)
let set_name c name =
c.name := name
However in this case Character.t = MCharacter.t = CharacterImpl.t, so you won't get the type safety you want
(A Character.t can still be modified by MCharacter.set_name).
Perhaps it'd be better to use different types, though to_character is not the identity function:
character.mli:
type t
val create : string -> t
val name : t -> string
mCharacter.mli:
include module type of Character
val set_name : t -> string -> unit
val to_character : t -> Character.t
character.ml:
include MCharacter
mCharacter.ml:
type t = {name : string ref}
let create name =
{name = ref name }
let name c = !(c.name)
let set_name c name =
c.name := name
let to_character x = Character.create (name x)
In fact you should probably take a look at String and Bytes type in OCaml 4.02 (and the ocaml-bytes compatibility lib for <4.0.2).
I'd prefer something simpler though:
character.ml:
type u = {name : string ref}
type 'a t = u
let create name =
{name = ref name }
let create_ro = create
let create_rw = create
let name c = !(c.name)
let set_name c name =
c.name := name
let readonly x = x
character.mli:
type 'a t constraint 'a = [< `W | `R]
val create_ro : string -> [`R] t
val create_rw : string -> [`R | `W] t
val name : 'a t -> string
val set_name : [> `W] t -> string -> unit
val readonly : [> `R] t -> [`R] t
Best regards,
--Edwin
next prev parent reply other threads:[~2014-08-06 15:36 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-08-06 12:14 Trevor Smith
2014-08-06 15:36 ` Török Edwin [this message]
2014-08-07 22:06 ` Trevor Smith
2014-08-08 8:19 ` Frédéric Bour
2014-08-06 22:06 ` Nick Lucaroni
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=53E24B96.8080402@etorok.net \
--to=edwin+ml-ocaml@etorok.net \
--cc=caml-list@inria.fr \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox