Mailing list for all users of the OCaml language and system.
 help / color / mirror / Atom feed
* Private and type constraints
@ 2008-08-05 15:08 Dario Teixeira
  2008-08-09 16:08 ` [Caml-list] " Dario Teixeira
  0 siblings, 1 reply; 2+ messages in thread
From: Dario Teixeira @ 2008-08-05 15:08 UTC (permalink / raw)
  To: caml-list

Hi,

With 'private', you can make sure that users of a module can only use
constructors to create values, while at the same type maintaining the
ability to pattern-match (which abstracting the type makes impossible).
With 3.10, this can also be done with polymorphic variants:

module Foobar:
sig
    type foo_t = [ `A ]
    type bar_t = [ `B ]
    type foobar_t = [ foo_t | bar_t ]
    type t = private [< foobar_t ]

    val make_a: unit -> t
    val make_b: unit -> t
end =
struct
    type foo_t = [ `A ]
    type bar_t = [ `B ]
    type foobar_t = [ foo_t | bar_t ]
    type t = foobar_t

    let make_a () = `A
    let make_b () = `B
end


# open Foobar;;
# let ola = make_a ();;
val ola : Foobar.t = `A
# match ola with `A -> true | `B -> false;;
- : bool = true
# let ola2 : Foobar.t = `A;;
Characters 22-24:
  let ola2 : Foobar.t = `A;;
                        ^^
Error: This expression has type [> `A ] but is here used with type Foobar.t
       Types for tag `A are incompatible


Now, I want to do the same for a type 't' that is declared using a type constraint.
There are however two problems: first, the code below is accepted by the toplevel,
but not by the ocamlc/ocamlopt compilers (I'm running version 3.11+dev15); second,
while as expected it prevents the creation of Foobar2.t values without using the
constructor functions, pattern-matching is unfortunately also disallowed.

module Foobar2:
sig
    type foo_t = [ `A ]
    type bar_t = [ `B ]
    type foobar_t = [ foo_t | bar_t ]
    type 'a t = private 'a constraint 'a = [< foobar_t ]

    val make_a: unit -> foo_t t
    val make_b: unit -> bar_t t
end =
struct
    type foo_t = [ `A ]
    type bar_t = [ `B ]
    type foobar_t = [ foo_t | bar_t ]
    type 'a t = 'a constraint 'a = [< foobar_t ]

    let make_a () = `A
    let make_b () = `B
end


# open Foobar2;;
# let ola = make_a ();;
val ola : Foobar2.foo_t Foobar2.t = `A
# match ola with `A -> true;;
Characters 15-17:
  match ola with `A -> true;;
                 ^^
Error: This pattern matches values of type [< `A ]
       but is here used to match values of type Foobar2.foo_t Foobar2.t
# let ola2 : Foobar2.foo_t Foobar2.t = `A;;
Characters 37-39:
  let ola2 : Foobar2.foo_t Foobar2.t = `A;;
                                       ^^
Error: This expression has type [> `A ] but is here used with type
         Foobar2.foo_t Foobar2.t


This is the error produced by the compiler:

Error: The implementation constraint.ml
       does not match the interface (inferred signature):
       Modules do not match:
         sig
           type foo_t = [ `A ]
           type bar_t = [ `B ]
           type foobar_t = [ `A | `B ]
           type 'a t = 'a Foobar2.t constraint 'a = [< foobar_t ]
           val make_a : unit -> foo_t t
           val make_b : unit -> bar_t t
         end
       is not included in
         sig
           type foo_t = [ `A ]
           type bar_t = [ `B ]
           type foobar_t = [ `A | `B ]
           type 'a t = private 'a constraint 'a = [< foobar_t ]
           val make_a : unit -> foo_t t
           val make_b : unit -> bar_t t
         end
       Type declarations do not match:
         type 'a t = 'a Foobar2.t constraint 'a = [< foobar_t ]
       is not included in
         type 'a t = private 'a constraint 'a = [< foobar_t ]


Any idea on what is going on?  Also, is it at all possible to achieve
the 'private' semantics I am looking for with types declared using
a constraint?  I know I can do it by boxing the type inside a dummy
union or a record, but I would like to avoid that hassle if possible.

Thanks for your time + best regards,
Dario Teixeira



      __________________________________________________________
Not happy with your email address?.
Get the one you really want - millions of new email addresses available now at Yahoo! http://uk.docs.yahoo.com/ymail/new.html


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [Caml-list] Private and type constraints
  2008-08-05 15:08 Private and type constraints Dario Teixeira
@ 2008-08-09 16:08 ` Dario Teixeira
  0 siblings, 0 replies; 2+ messages in thread
From: Dario Teixeira @ 2008-08-09 16:08 UTC (permalink / raw)
  To: caml-list

Hi,

I just noted that there's already a ticket (#4580) related to this problem:
http://caml.inria.fr/mantis/view.php?id=4580

My doubts are a) whether the code below will be correct for 3.11 final;
and b) whether its semantics are equivalent to other uses of 'private',
namely that external pattern-matching on Foobar.t values is allowed,
but the construction of new values must be done through the constructor
functions.  Any thoughts?

Thanks in advance for your time!
Cheers,
Dario Teixeira
 
module Foobar:
sig
  type foo_t= [ `A ]
  type bar_t = [ `B ]
  type foobar_t = [ foo_t | bar_t ]
  type 'a t = private 'a constraint 'a = [< foobar_t ]
 
  val make_a: unit -> foo_t t
  val make_b: unit -> bar_t t
end =
struct
  type foo_t = [ `A ]
  type bar_t = [ `B ]
  type foobar_t = [ foo_t | bar_t ]
  type 'a t = 'a constraint 'a = [< foobar_t ]

  let make_a () = `A
  let make_b () = `B
end



      __________________________________________________________
Not happy with your email address?.
Get the one you really want - millions of new email addresses available now at Yahoo! http://uk.docs.yahoo.com/ymail/new.html


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2008-08-09 16:09 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-08-05 15:08 Private and type constraints Dario Teixeira
2008-08-09 16:08 ` [Caml-list] " Dario Teixeira

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox