* [Caml-list] Trying to define a functor combining polymorphic variants
@ 2014-05-01 20:58 Berke Durak
2014-05-01 23:55 ` Leo White
2014-05-02 6:14 ` Jacques Garrigue
0 siblings, 2 replies; 5+ messages in thread
From: Berke Durak @ 2014-05-01 20:58 UTC (permalink / raw)
To: caml-list
Hello all,
I have been using the following kind of construct:
module A = struct
type message = [`Alpha]
let string_of_message = function `Alpha -> "alpha"
end
module B = struct
type message = [`Beta]
let string_of_message = function `Beta -> "beta"
end
module AB = struct
type message = [ A.message | B.message ]
let string_of_message = function
| #A.message as msg -> A.string_of_message msg
| #B.message as msg -> B.string_of_message msg
end
So I naturally wanted to write a functor that does what the module AB does:
module type S = sig
type message
val string_of_message : message -> string
end
module PROD(A : S)(B : S) = struct
type message = [ A.message | B.message ]
let string_of_message = function
| #A.t as msg -> A.string_of_message msg
| #B.t as msg -> B.string_of_message msg
end
But we (me + people on #ocaml: mrvn, drup, ggole, whitequark...) couldn't find a
way to specify, in the signature S, that message is a polymorphic variant so
that [ A.message | B.message ] is legal.
We tried things like:
module type S = sig type 'a t = ([> ] as 'a) end
module PROD(X : S)(Y : S) = struct
type ('a,'b) t = [ 'a X.t | 'b Y.t ]
end
but all we get is:
Error: The type [> ] A.message is not a polymorphic variant type
Any suggestions?
--
Berke Durak
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Caml-list] Trying to define a functor combining polymorphic variants
2014-05-01 20:58 [Caml-list] Trying to define a functor combining polymorphic variants Berke Durak
@ 2014-05-01 23:55 ` Leo White
2014-05-02 6:14 ` Jacques Garrigue
1 sibling, 0 replies; 5+ messages in thread
From: Leo White @ 2014-05-01 23:55 UTC (permalink / raw)
To: Berke Durak; +Cc: caml-list
Hi,
I'm afraid that I don't think you can do what you are trying to
do. Without going into full detail, consider what would happen with your
imagined functor `PROD` in the following case:
module A = struct
type message = [`Alpha of int]
let string_of_message = function `Alpha i -> string_of_int i
end
module B = struct
type message = [`Alpha of string]
let string_of_message = function `Alpha s -> s
end
let b : B.message = `Alpha "hello"
module AB = PROD(A)(B)
let bad = AB.string_of_message b
`b` would match the pattern for `#A.message`, and you would get a
segfault. It is not sufficient to restrict `A.message` and `B.message`
to be polymorphic variants, they must be polymorphic variants that share
no tags.
Regards,
Leo
Berke Durak <berke.durak@gmail.com> writes:
> Hello all,
>
> I have been using the following kind of construct:
>
> module A = struct
> type message = [`Alpha]
> let string_of_message = function `Alpha -> "alpha"
> end
>
> module B = struct
> type message = [`Beta]
> let string_of_message = function `Beta -> "beta"
> end
>
> module AB = struct
> type message = [ A.message | B.message ]
> let string_of_message = function
> | #A.message as msg -> A.string_of_message msg
> | #B.message as msg -> B.string_of_message msg
> end
>
> So I naturally wanted to write a functor that does what the module AB does:
>
> module type S = sig
> type message
> val string_of_message : message -> string
> end
>
> module PROD(A : S)(B : S) = struct
> type message = [ A.message | B.message ]
> let string_of_message = function
> | #A.t as msg -> A.string_of_message msg
> | #B.t as msg -> B.string_of_message msg
> end
>
> But we (me + people on #ocaml: mrvn, drup, ggole, whitequark...) couldn't find a
> way to specify, in the signature S, that message is a polymorphic variant so
> that [ A.message | B.message ] is legal.
>
> We tried things like:
>
> module type S = sig type 'a t = ([> ] as 'a) end
>
> module PROD(X : S)(Y : S) = struct
> type ('a,'b) t = [ 'a X.t | 'b Y.t ]
> end
>
> but all we get is:
>
> Error: The type [> ] A.message is not a polymorphic variant type
>
> Any suggestions?
> --
> Berke Durak
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Caml-list] Trying to define a functor combining polymorphic variants
2014-05-01 20:58 [Caml-list] Trying to define a functor combining polymorphic variants Berke Durak
2014-05-01 23:55 ` Leo White
@ 2014-05-02 6:14 ` Jacques Garrigue
2014-05-02 15:50 ` Berke Durak
1 sibling, 1 reply; 5+ messages in thread
From: Jacques Garrigue @ 2014-05-02 6:14 UTC (permalink / raw)
To: Berke Durak; +Cc: Mailing List OCaml
On 2014/05/02 05:58, Berke Durak wrote:
> So I naturally wanted to write a functor that does what the module AB does:
>
> module type S = sig
> type message
> val string_of_message : message -> string
> end
>
> module PROD(A : S)(B : S) = struct
> type message = [ A.message | B.message ]
> let string_of_message = function
> | #A.t as msg -> A.string_of_message msg
> | #B.t as msg -> B.string_of_message msg
> end
>
> But we (me + people on #ocaml: mrvn, drup, ggole, whitequark...) couldn't find a
> way to specify, in the signature S, that message is a polymorphic variant so
> that [ A.message | B.message ] is legal.
There is a branch of the compiler which allows you to do that.
http://caml.inria.fr/cgi-bin/viewvc.cgi/ocaml/branches/varunion/
Note that it contains only part of the directories. You can get the others
from a pristine 3.10.
Using that version, you would write:
module type S = sig
type message = private [> ]
…
end
module PROD (A : S) (B : S with type message = private [> ] ~ A.message) = …
where the ~ is a compatibility annotation.
This was never merged because I couldn’t find a clean way to fix some gap between
theory and practice, but I may give it another try.
Keigo Imai used it in his async_session code.
https://github.com/keigoi/async_session/blob/master/varunion_session.ml
Jacques Garrigue
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Caml-list] Trying to define a functor combining polymorphic variants
2014-05-02 6:14 ` Jacques Garrigue
@ 2014-05-02 15:50 ` Berke Durak
2014-05-03 1:43 ` Jacques Garrigue
0 siblings, 1 reply; 5+ messages in thread
From: Berke Durak @ 2014-05-02 15:50 UTC (permalink / raw)
To: Jacques Garrigue; +Cc: Mailing List OCaml
Thanks Leo and Jacques for the responses.
Jacques, if the PROD functor has to have a compatibility tag, doesn't
it mean that you can't reuse it to generate large products? i.e. how
would one write: A*B*C*D = PROD(A)(PROD(B)(PROD(C)(D))))?
On Fri, May 2, 2014 at 2:14 AM, Jacques Garrigue
<garrigue@math.nagoya-u.ac.jp> wrote:
> On 2014/05/02 05:58, Berke Durak wrote:
>> So I naturally wanted to write a functor that does what the module AB does:
>>
>> module type S = sig
>> type message
>> val string_of_message : message -> string
>> end
>>
>> module PROD(A : S)(B : S) = struct
>> type message = [ A.message | B.message ]
>> let string_of_message = function
>> | #A.t as msg -> A.string_of_message msg
>> | #B.t as msg -> B.string_of_message msg
>> end
>>
>> But we (me + people on #ocaml: mrvn, drup, ggole, whitequark...) couldn't find a
>> way to specify, in the signature S, that message is a polymorphic variant so
>> that [ A.message | B.message ] is legal.
>
> There is a branch of the compiler which allows you to do that.
>
> http://caml.inria.fr/cgi-bin/viewvc.cgi/ocaml/branches/varunion/
>
> Note that it contains only part of the directories. You can get the others
> from a pristine 3.10.
>
> Using that version, you would write:
> module type S = sig
> type message = private [> ]
> …
> end
>
> module PROD (A : S) (B : S with type message = private [> ] ~ A.message) = …
>
> where the ~ is a compatibility annotation.
>
> This was never merged because I couldn’t find a clean way to fix some gap between
> theory and practice, but I may give it another try.
> Keigo Imai used it in his async_session code.
>
> https://github.com/keigoi/async_session/blob/master/varunion_session.ml
>
> Jacques Garrigue
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Caml-list] Trying to define a functor combining polymorphic variants
2014-05-02 15:50 ` Berke Durak
@ 2014-05-03 1:43 ` Jacques Garrigue
0 siblings, 0 replies; 5+ messages in thread
From: Jacques Garrigue @ 2014-05-03 1:43 UTC (permalink / raw)
To: Berke Durak; +Cc: OCaML List Mailing
On 2014/05/03 00:50, Berke Durak wrote:
>
> Thanks Leo and Jacques for the responses.
>
> Jacques, if the PROD functor has to have a compatibility tag, doesn't
> it mean that you can't reuse it to generate large products? i.e. how
> would one write: A*B*C*D = PROD(A)(PROD(B)(PROD(C)(D))))?
The compatibility annotation is on the functor. If the variant types
in the modules you pass to the functor are concrete, they don’t need
annotations.
If you want to define a 4-ary functor that calls PROD, then its arguments
will need annotations too, of course.
For the details, you can see the internship report by Romain Bardou (in French):
Unions de variants polymorphes abstraits
http://www.math.nagoya-u.ac.jp/~garrigue/papers/index.html
Jacques Garrigue
> On Fri, May 2, 2014 at 2:14 AM, Jacques Garrigue
> <garrigue@math.nagoya-u.ac.jp> wrote:
>> On 2014/05/02 05:58, Berke Durak wrote:
>>> So I naturally wanted to write a functor that does what the module AB does:
>>>
>>> module type S = sig
>>> type message
>>> val string_of_message : message -> string
>>> end
>>>
>>> module PROD(A : S)(B : S) = struct
>>> type message = [ A.message | B.message ]
>>> let string_of_message = function
>>> | #A.t as msg -> A.string_of_message msg
>>> | #B.t as msg -> B.string_of_message msg
>>> end
>>>
>>> But we (me + people on #ocaml: mrvn, drup, ggole, whitequark...) couldn't find a
>>> way to specify, in the signature S, that message is a polymorphic variant so
>>> that [ A.message | B.message ] is legal.
>>
>> There is a branch of the compiler which allows you to do that.
>>
>> http://caml.inria.fr/cgi-bin/viewvc.cgi/ocaml/branches/varunion/
>>
>> Note that it contains only part of the directories. You can get the others
>> from a pristine 3.10.
>>
>> Using that version, you would write:
>> module type S = sig
>> type message = private [> ]
>> …
>> end
>>
>> module PROD (A : S) (B : S with type message = private [> ] ~ A.message) = …
>>
>> where the ~ is a compatibility annotation.
>>
>> This was never merged because I couldn’t find a clean way to fix some gap between
>> theory and practice, but I may give it another try.
>> Keigo Imai used it in his async_session code.
>>
>> https://github.com/keigoi/async_session/blob/master/varunion_session.ml
>>
>> Jacques Garrigue
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2014-05-03 1:44 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-05-01 20:58 [Caml-list] Trying to define a functor combining polymorphic variants Berke Durak
2014-05-01 23:55 ` Leo White
2014-05-02 6:14 ` Jacques Garrigue
2014-05-02 15:50 ` Berke Durak
2014-05-03 1:43 ` Jacques Garrigue
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox