caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Philippe Veber <philippe.veber@gmail.com>
To: Jacques Garrigue <garrigue@math.nagoya-u.ac.jp>
Cc: caml users <caml-list@inria.fr>
Subject: Re: [Caml-list] Explicitely named type variable and type constraints.
Date: Wed, 21 Mar 2012 10:41:39 +0100	[thread overview]
Message-ID: <CAOOOohQLL=rprd0za=o8JHcvv4r_+N2XwtC-hWQf1W3vRAosMg@mail.gmail.com> (raw)
In-Reply-To: <3EB8D30A-FB02-4654-9F95-B7FF029F02FE@math.nagoya-u.ac.jp>

[-- Attachment #1: Type: text/plain, Size: 5187 bytes --]

Thanks for your answer Jacques!

>          ([> `quit ] as 'a) screen = (module Screen with type message =
> 'a)
> >        but an expression was expected of type (module Screen)
>
> Indeed, this is clearly wrong: these two module types are not equivalent.
>
Right, that one was obvious.


> > New attempt:
> >
> > # let f (screen : 'a screen) =
> >     let module Screen = (val screen : Screen with type message = 'a) in
> >     match Screen.(emit init) with
> >       | Some `quit -> 1
> >       | _ -> 0
> >
> >   ;;
> > Error: Unbound type parameter 'a
>
> Wrong again, as subtyping between module signatures does not
> allow free type variables.
>
At some point, I remember having a message saying that indeed type
variables are not allowed while unpacking the module, at least something
closer to what you say and more specific than "unbound type parameter 'a".
So I'd say it would be more convenient to have a specific message (just
like there is for unbound type variables in class definitions for
instance). If you don't consider it too futile, I can test it on the SVN
head and file a bug report if appropriate.


>
> > Though here I'm not sure the error is right. New attempt:
> >
> >
> > # let f (type s) (screen : s screen) =
> >     let module Screen = (val screen : Screen with type message = s) in
> >     match Screen.(emit init) with
> >       | Some `quit -> 1
> >       | _ -> 0
> >
> >   ;;
> > Error: This type s should be an instance of type [> `quit ]
> >
> > Which makes sense. So here is my question: is there a way to impose a
> constraint on the "newtype" introduced in argument? Let me say that I'm
> aware I should write this more simply. For instance in the module type
> Screen, emit could have type state -> [`quit | `message of message]. So my
> question is only a matter of curiosity. Still, I'd be happy to know :o).
>
> No, currently there is no way to do that.
> One can only create locally abstract types, not locally private types.
>
Ok.


> In theory I see no problem doing that, but with the current approach this
> would require new syntax,
> and be rather heavy.
>
>  let f (type s = private [> `quit]) (screen : s screen) = ...
>
> And to be fully general, recursion between those types should be allowed
> too...
>
Probably not worth the trouble. I'm just not used to writing a type and not
being able to write a function using values of this type afterwards :o).


>
> As a side note, writing
>        type message = private [> unit]
> makes the problem clearer.
> And solves it in some cases:
>
> module type Screen =
>  sig
>    type state
>     type message = private [> `quit ]
>    val init : state
>     val emit : state -> message option
>  end
> # let f (module Screen : Screen) =
>     match Screen.(emit init) with
>    | Some `quit -> 1
>    | _ -> 0
>  ;;
> val f : (module Screen) -> int = <fun>
>
Indeed that works! (with appropriate 3.12 syntax).

# module type Screen
=

 sig

   type
state

   type message = private [> `quit
]

   val init :
state

   val emit : state -> message
option

 end;;

module type Screen
=


sig

    type
state

    type message = private [> `quit ]
    val init : state
    val emit : state -> message option
  end
# let f screen = let module Screen = (val screen : Screen) in match
Screen.emit Screen.init with Some `quit -> 1 | _ ->
0;;
val f : (module Screen) -> int =
<fun>

# module Screen1 : Screen = struct type state = unit type message = [`a |
`quit] let init = () let emit () = Some `a
end;;
module Screen1 :
Screen

# module Screen2 : Screen = struct type state = int type message = [`a |
`quit] let init = 0 let emit _ = Some `quit
end;;
module Screen2 :
Screen

# [ (module Screen1 : Screen) ; (module Screen2 : Screen)
];;

- : (module Screen) list = [<module>;
<module>]


This nearly solves my problem: there will be several Screen modules, and
those should share a common message type, so that they can communicate.
That's why I introduced the 'a screen type. However, it seems that I can't
define it anymore:

# type 'a screen = (module Screen with type message = 'a) constraint 'a =
[>
`quit];;

Error: In this `with' constraint, the new definition of
message

       does not match its original definition in the constrained
signature:

       Type declarations do not
match:

         type message
       is not included in
         type message = private [> `quit ]

# type 'a screen = (module Screen with type message = 'a constraint 'a = [>
`quit]);;

Error: Syntax
error


It's only logical the first attempt fails. The second, however, seems more
reasonable to me (but I guess if type constraints are only allowed in type
definition there must be a good reason). Is there a workaround? In the end,
I'd want to define a list of Screen modules that share a common message
type containing the `quit tag. That said, I remember the work by Romain
Bardou and yourself on unions of private polymorphic variants, and I guess
we might face difficult problems here. In any case, I have a backup
solution, so it's no big deal if it isn't possible.



> (using 4.00, but you can also write with (val ...))
>
> That remark was unfortunate: now my thread is spoiled for sure :o)))

[-- Attachment #2: Type: text/html, Size: 10104 bytes --]

      parent reply	other threads:[~2012-03-21  9:42 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-03-21  7:48 Philippe Veber
2012-03-21  8:21 ` Jacques Garrigue
2012-03-21  8:54   ` Alan Schmitt
2012-03-21  9:01     ` Thomas Braibant
2012-03-21  9:29       ` Alain Frisch
2012-03-21  9:41   ` Philippe Veber [this message]

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='CAOOOohQLL=rprd0za=o8JHcvv4r_+N2XwtC-hWQf1W3vRAosMg@mail.gmail.com' \
    --to=philippe.veber@gmail.com \
    --cc=caml-list@inria.fr \
    --cc=garrigue@math.nagoya-u.ac.jp \
    /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;
as well as URLs for NNTP newsgroup(s).