* [Caml-list] Weird type error involving 'include' and applicative functors
@ 2015-02-13 21:40 Carl Eastlund
2015-02-15 10:26 ` Gabriel Scherer
0 siblings, 1 reply; 8+ messages in thread
From: Carl Eastlund @ 2015-02-13 21:40 UTC (permalink / raw)
To: caml-list
[-- Attachment #1: Type: text/plain, Size: 1730 bytes --]
This seems to be a compiler bug, but let me know if I've missed something.
The behavior I see is that Make_ok1 and Make_ok2 compile fine, but the very
similar functor Make_bad does not. I get this compile error:
========================================
Error: Signature mismatch:
Modules do not match:
sig
module C : sig module T : sig end type t = Make(T).t end
module T = C.T
type t = Make(T).t
end
is not included in
sig type t module C : sig type t = t end end
In module C:
Modules do not match:
sig module T : sig end type t = Make(T).t end
is not included in
sig type t = C.t end
In module C:
Type declarations do not match:
type t = Make(T).t
is not included in
type t = t
========================================
And here is the code:
========================================
module type S = sig type t end
module Make (M : sig end) : S = struct type t end
module Make_ok1 (M : sig end) : sig
type t
module A : S with type t = t
end = struct
module A = struct
include Make (struct end)
end
include A
end
module Make_ok2 (M : sig end) : sig
type t
module B : S with type t = t
end = struct
module T = struct end
module B = struct
include Make (T)
end
include B
end
module Make_bad (M : sig end) : sig
type t
module C : S with type t = t
end = struct
module C = struct
module T = struct end
include Make (T)
end
include C
end
========================================
--
Carl Eastlund
[-- Attachment #2: Type: text/html, Size: 2855 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Caml-list] Weird type error involving 'include' and applicative functors
2015-02-13 21:40 [Caml-list] Weird type error involving 'include' and applicative functors Carl Eastlund
@ 2015-02-15 10:26 ` Gabriel Scherer
2015-02-16 18:03 ` Leo White
2015-02-24 4:38 ` Jacques Garrigue
0 siblings, 2 replies; 8+ messages in thread
From: Gabriel Scherer @ 2015-02-15 10:26 UTC (permalink / raw)
To: Carl Eastlund; +Cc: caml users
That is one of the dark corners of the module system.
I don't know whether an ideal type-checker should accept your last
definition or not. It is non-intuitive that some are accepted and
others rejected; some things in the module system are non-intuitive
for good reasons, some others because of implementation limitations,
and it's not always clear to non-experts which is which).˙But I can
explain why the last definition is harder for the type-checker to
accept than the other.
# module A = struct
module T = struct end
module C = struct
include Make(T)
end
include C
end
;;
module A :
sig
module T : sig end
module C : sig type t = Make(T).t end
type t = Make(T).t
end
# module B = struct
module C = struct
module T = struct end
include Make(T)
end
include C
end
;;
module B :
sig
module C : sig module T : sig end type t = Make(T).t end
module T = C.T
type t = Make(T).t
end
Note the important difference in the inferred signatures in both
cases. Both modules have
type t = Make(T).t
but, in the first case, this is the *same module T* that is mentioned
in the signature of T, while in the second case, there are two
different modules, C.T and T (the latter being generated by the
"include", with an equation that it is equal to the former).
The reasoning to check against your signature
sig
type t
module C : S with type t = t
end
is thus more complicated in the second case: the type-checker would
need to use the equation (T = C.T) to check that indeed C.t is equal
to t.
I think this is due to the rather contorted way you define C first in
the implementations and include it later, while in the signature first
define t and then C. Note that the following signature, which is
morally equivalent, accepts both implementations (and thus all the
functors in your file):
sig
module C : S
type t = C.t
end
On Fri, Feb 13, 2015 at 10:40 PM, Carl Eastlund
<ceastlund@janestreet.com> wrote:
> This seems to be a compiler bug, but let me know if I've missed something.
> The behavior I see is that Make_ok1 and Make_ok2 compile fine, but the very
> similar functor Make_bad does not. I get this compile error:
>
> ========================================
>
> Error: Signature mismatch:
> Modules do not match:
> sig
> module C : sig module T : sig end type t = Make(T).t end
> module T = C.T
> type t = Make(T).t
> end
> is not included in
> sig type t module C : sig type t = t end end
> In module C:
> Modules do not match:
> sig module T : sig end type t = Make(T).t end
> is not included in
> sig type t = C.t end
> In module C:
> Type declarations do not match:
> type t = Make(T).t
> is not included in
> type t = t
>
> ========================================
>
> And here is the code:
>
> ========================================
>
> module type S = sig type t end
> module Make (M : sig end) : S = struct type t end
>
> module Make_ok1 (M : sig end) : sig
>
> type t
> module A : S with type t = t
>
> end = struct
>
> module A = struct
> include Make (struct end)
> end
> include A
>
> end
>
> module Make_ok2 (M : sig end) : sig
>
> type t
> module B : S with type t = t
>
> end = struct
>
> module T = struct end
> module B = struct
> include Make (T)
> end
> include B
>
> end
>
> module Make_bad (M : sig end) : sig
>
> type t
> module C : S with type t = t
>
> end = struct
>
> module C = struct
> module T = struct end
> include Make (T)
> end
> include C
>
> end
>
> ========================================
>
> --
> Carl Eastlund
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Caml-list] Weird type error involving 'include' and applicative functors
2015-02-15 10:26 ` Gabriel Scherer
@ 2015-02-16 18:03 ` Leo White
2015-02-17 21:40 ` Milan Stanojević
2015-02-24 4:38 ` Jacques Garrigue
1 sibling, 1 reply; 8+ messages in thread
From: Leo White @ 2015-02-16 18:03 UTC (permalink / raw)
To: Gabriel Scherer; +Cc: Carl Eastlund, caml users
Gabriel gives an accurate accout of what is going on. To me, it looks
like the type-checker should probably accept this, so I would submit it
as a bug (I suspect a missing call to Env.normalize_path somewhere, but
perhaps there is something more significant going on here).
Regards,
Leo
Gabriel Scherer <gabriel.scherer@gmail.com> writes:
> That is one of the dark corners of the module system.
>
> I don't know whether an ideal type-checker should accept your last
> definition or not. It is non-intuitive that some are accepted and
> others rejected; some things in the module system are non-intuitive
> for good reasons, some others because of implementation limitations,
> and it's not always clear to non-experts which is which).˙But I can
> explain why the last definition is harder for the type-checker to
> accept than the other.
>
> # module A = struct
> module T = struct end
> module C = struct
> include Make(T)
> end
> include C
> end
> ;;
> module A :
> sig
> module T : sig end
> module C : sig type t = Make(T).t end
> type t = Make(T).t
> end
>
> # module B = struct
> module C = struct
> module T = struct end
> include Make(T)
> end
> include C
> end
> ;;
> module B :
> sig
> module C : sig module T : sig end type t = Make(T).t end
> module T = C.T
> type t = Make(T).t
> end
>
>
> Note the important difference in the inferred signatures in both
> cases. Both modules have
> type t = Make(T).t
> but, in the first case, this is the *same module T* that is mentioned
> in the signature of T, while in the second case, there are two
> different modules, C.T and T (the latter being generated by the
> "include", with an equation that it is equal to the former).
>
> The reasoning to check against your signature
> sig
> type t
> module C : S with type t = t
> end
> is thus more complicated in the second case: the type-checker would
> need to use the equation (T = C.T) to check that indeed C.t is equal
> to t.
>
> I think this is due to the rather contorted way you define C first in
> the implementations and include it later, while in the signature first
> define t and then C. Note that the following signature, which is
> morally equivalent, accepts both implementations (and thus all the
> functors in your file):
> sig
> module C : S
> type t = C.t
> end
>
>
> On Fri, Feb 13, 2015 at 10:40 PM, Carl Eastlund
> <ceastlund@janestreet.com> wrote:
>> This seems to be a compiler bug, but let me know if I've missed something.
>> The behavior I see is that Make_ok1 and Make_ok2 compile fine, but the very
>> similar functor Make_bad does not. I get this compile error:
>>
>> ========================================
>>
>> Error: Signature mismatch:
>> Modules do not match:
>> sig
>> module C : sig module T : sig end type t = Make(T).t end
>> module T = C.T
>> type t = Make(T).t
>> end
>> is not included in
>> sig type t module C : sig type t = t end end
>> In module C:
>> Modules do not match:
>> sig module T : sig end type t = Make(T).t end
>> is not included in
>> sig type t = C.t end
>> In module C:
>> Type declarations do not match:
>> type t = Make(T).t
>> is not included in
>> type t = t
>>
>> ========================================
>>
>> And here is the code:
>>
>> ========================================
>>
>> module type S = sig type t end
>> module Make (M : sig end) : S = struct type t end
>>
>> module Make_ok1 (M : sig end) : sig
>>
>> type t
>> module A : S with type t = t
>>
>> end = struct
>>
>> module A = struct
>> include Make (struct end)
>> end
>> include A
>>
>> end
>>
>> module Make_ok2 (M : sig end) : sig
>>
>> type t
>> module B : S with type t = t
>>
>> end = struct
>>
>> module T = struct end
>> module B = struct
>> include Make (T)
>> end
>> include B
>>
>> end
>>
>> module Make_bad (M : sig end) : sig
>>
>> type t
>> module C : S with type t = t
>>
>> end = struct
>>
>> module C = struct
>> module T = struct end
>> include Make (T)
>> end
>> include C
>>
>> end
>>
>> ========================================
>>
>> --
>> Carl Eastlund
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Caml-list] Weird type error involving 'include' and applicative functors
2015-02-16 18:03 ` Leo White
@ 2015-02-17 21:40 ` Milan Stanojević
2015-02-19 18:21 ` Milan Stanojević
0 siblings, 1 reply; 8+ messages in thread
From: Milan Stanojević @ 2015-02-17 21:40 UTC (permalink / raw)
To: Leo White; +Cc: Gabriel Scherer, Carl Eastlund, caml users
It seems that type checker does know that C.T and T are aliases since
this compiles
module C = struct
module T = struct end
include Make (T)
end
include C
let f (x : Make(Make(T)).t) : Make(Make(C.T)).t = x
Somehow the fact that C.T = T is lost when checking against the signature.
On Mon, Feb 16, 2015 at 1:03 PM, Leo White <lpw25@cam.ac.uk> wrote:
> Gabriel gives an accurate accout of what is going on. To me, it looks
> like the type-checker should probably accept this, so I would submit it
> as a bug (I suspect a missing call to Env.normalize_path somewhere, but
> perhaps there is something more significant going on here).
>
> Regards,
>
> Leo
>
> Gabriel Scherer <gabriel.scherer@gmail.com> writes:
>
>> That is one of the dark corners of the module system.
>>
>> I don't know whether an ideal type-checker should accept your last
>> definition or not. It is non-intuitive that some are accepted and
>> others rejected; some things in the module system are non-intuitive
>> for good reasons, some others because of implementation limitations,
>> and it's not always clear to non-experts which is which).˙But I can
>> explain why the last definition is harder for the type-checker to
>> accept than the other.
>>
>> # module A = struct
>> module T = struct end
>> module C = struct
>> include Make(T)
>> end
>> include C
>> end
>> ;;
>> module A :
>> sig
>> module T : sig end
>> module C : sig type t = Make(T).t end
>> type t = Make(T).t
>> end
>>
>> # module B = struct
>> module C = struct
>> module T = struct end
>> include Make(T)
>> end
>> include C
>> end
>> ;;
>> module B :
>> sig
>> module C : sig module T : sig end type t = Make(T).t end
>> module T = C.T
>> type t = Make(T).t
>> end
>>
>>
>> Note the important difference in the inferred signatures in both
>> cases. Both modules have
>> type t = Make(T).t
>> but, in the first case, this is the *same module T* that is mentioned
>> in the signature of T, while in the second case, there are two
>> different modules, C.T and T (the latter being generated by the
>> "include", with an equation that it is equal to the former).
>>
>> The reasoning to check against your signature
>> sig
>> type t
>> module C : S with type t = t
>> end
>> is thus more complicated in the second case: the type-checker would
>> need to use the equation (T = C.T) to check that indeed C.t is equal
>> to t.
>>
>> I think this is due to the rather contorted way you define C first in
>> the implementations and include it later, while in the signature first
>> define t and then C. Note that the following signature, which is
>> morally equivalent, accepts both implementations (and thus all the
>> functors in your file):
>> sig
>> module C : S
>> type t = C.t
>> end
>>
>>
>> On Fri, Feb 13, 2015 at 10:40 PM, Carl Eastlund
>> <ceastlund@janestreet.com> wrote:
>>> This seems to be a compiler bug, but let me know if I've missed something.
>>> The behavior I see is that Make_ok1 and Make_ok2 compile fine, but the very
>>> similar functor Make_bad does not. I get this compile error:
>>>
>>> ========================================
>>>
>>> Error: Signature mismatch:
>>> Modules do not match:
>>> sig
>>> module C : sig module T : sig end type t = Make(T).t end
>>> module T = C.T
>>> type t = Make(T).t
>>> end
>>> is not included in
>>> sig type t module C : sig type t = t end end
>>> In module C:
>>> Modules do not match:
>>> sig module T : sig end type t = Make(T).t end
>>> is not included in
>>> sig type t = C.t end
>>> In module C:
>>> Type declarations do not match:
>>> type t = Make(T).t
>>> is not included in
>>> type t = t
>>>
>>> ========================================
>>>
>>> And here is the code:
>>>
>>> ========================================
>>>
>>> module type S = sig type t end
>>> module Make (M : sig end) : S = struct type t end
>>>
>>> module Make_ok1 (M : sig end) : sig
>>>
>>> type t
>>> module A : S with type t = t
>>>
>>> end = struct
>>>
>>> module A = struct
>>> include Make (struct end)
>>> end
>>> include A
>>>
>>> end
>>>
>>> module Make_ok2 (M : sig end) : sig
>>>
>>> type t
>>> module B : S with type t = t
>>>
>>> end = struct
>>>
>>> module T = struct end
>>> module B = struct
>>> include Make (T)
>>> end
>>> include B
>>>
>>> end
>>>
>>> module Make_bad (M : sig end) : sig
>>>
>>> type t
>>> module C : S with type t = t
>>>
>>> end = struct
>>>
>>> module C = struct
>>> module T = struct end
>>> include Make (T)
>>> end
>>> include C
>>>
>>> end
>>>
>>> ========================================
>>>
>>> --
>>> Carl Eastlund
>
> --
> Caml-list mailing list. Subscription management and archives:
> https://sympa.inria.fr/sympa/arc/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Caml-list] Weird type error involving 'include' and applicative functors
2015-02-17 21:40 ` Milan Stanojević
@ 2015-02-19 18:21 ` Milan Stanojević
2015-02-19 18:23 ` Milan Stanojević
0 siblings, 1 reply; 8+ messages in thread
From: Milan Stanojević @ 2015-02-19 18:21 UTC (permalink / raw)
To: Leo White; +Cc: Gabriel Scherer, Carl Eastlund, caml users
I submitted a bug report.
http://caml.inria.fr/mantis/view.php?id=6788
On Tue, Feb 17, 2015 at 4:40 PM, Milan Stanojević <milanst@gmail.com> wrote:
> It seems that type checker does know that C.T and T are aliases since
> this compiles
>
> module C = struct
> module T = struct end
> include Make (T)
> end
> include C
>
> let f (x : Make(Make(T)).t) : Make(Make(C.T)).t = x
>
> Somehow the fact that C.T = T is lost when checking against the signature.
>
>
>
>
> On Mon, Feb 16, 2015 at 1:03 PM, Leo White <lpw25@cam.ac.uk> wrote:
>> Gabriel gives an accurate accout of what is going on. To me, it looks
>> like the type-checker should probably accept this, so I would submit it
>> as a bug (I suspect a missing call to Env.normalize_path somewhere, but
>> perhaps there is something more significant going on here).
>>
>> Regards,
>>
>> Leo
>>
>> Gabriel Scherer <gabriel.scherer@gmail.com> writes:
>>
>>> That is one of the dark corners of the module system.
>>>
>>> I don't know whether an ideal type-checker should accept your last
>>> definition or not. It is non-intuitive that some are accepted and
>>> others rejected; some things in the module system are non-intuitive
>>> for good reasons, some others because of implementation limitations,
>>> and it's not always clear to non-experts which is which).˙But I can
>>> explain why the last definition is harder for the type-checker to
>>> accept than the other.
>>>
>>> # module A = struct
>>> module T = struct end
>>> module C = struct
>>> include Make(T)
>>> end
>>> include C
>>> end
>>> ;;
>>> module A :
>>> sig
>>> module T : sig end
>>> module C : sig type t = Make(T).t end
>>> type t = Make(T).t
>>> end
>>>
>>> # module B = struct
>>> module C = struct
>>> module T = struct end
>>> include Make(T)
>>> end
>>> include C
>>> end
>>> ;;
>>> module B :
>>> sig
>>> module C : sig module T : sig end type t = Make(T).t end
>>> module T = C.T
>>> type t = Make(T).t
>>> end
>>>
>>>
>>> Note the important difference in the inferred signatures in both
>>> cases. Both modules have
>>> type t = Make(T).t
>>> but, in the first case, this is the *same module T* that is mentioned
>>> in the signature of T, while in the second case, there are two
>>> different modules, C.T and T (the latter being generated by the
>>> "include", with an equation that it is equal to the former).
>>>
>>> The reasoning to check against your signature
>>> sig
>>> type t
>>> module C : S with type t = t
>>> end
>>> is thus more complicated in the second case: the type-checker would
>>> need to use the equation (T = C.T) to check that indeed C.t is equal
>>> to t.
>>>
>>> I think this is due to the rather contorted way you define C first in
>>> the implementations and include it later, while in the signature first
>>> define t and then C. Note that the following signature, which is
>>> morally equivalent, accepts both implementations (and thus all the
>>> functors in your file):
>>> sig
>>> module C : S
>>> type t = C.t
>>> end
>>>
>>>
>>> On Fri, Feb 13, 2015 at 10:40 PM, Carl Eastlund
>>> <ceastlund@janestreet.com> wrote:
>>>> This seems to be a compiler bug, but let me know if I've missed something.
>>>> The behavior I see is that Make_ok1 and Make_ok2 compile fine, but the very
>>>> similar functor Make_bad does not. I get this compile error:
>>>>
>>>> ========================================
>>>>
>>>> Error: Signature mismatch:
>>>> Modules do not match:
>>>> sig
>>>> module C : sig module T : sig end type t = Make(T).t end
>>>> module T = C.T
>>>> type t = Make(T).t
>>>> end
>>>> is not included in
>>>> sig type t module C : sig type t = t end end
>>>> In module C:
>>>> Modules do not match:
>>>> sig module T : sig end type t = Make(T).t end
>>>> is not included in
>>>> sig type t = C.t end
>>>> In module C:
>>>> Type declarations do not match:
>>>> type t = Make(T).t
>>>> is not included in
>>>> type t = t
>>>>
>>>> ========================================
>>>>
>>>> And here is the code:
>>>>
>>>> ========================================
>>>>
>>>> module type S = sig type t end
>>>> module Make (M : sig end) : S = struct type t end
>>>>
>>>> module Make_ok1 (M : sig end) : sig
>>>>
>>>> type t
>>>> module A : S with type t = t
>>>>
>>>> end = struct
>>>>
>>>> module A = struct
>>>> include Make (struct end)
>>>> end
>>>> include A
>>>>
>>>> end
>>>>
>>>> module Make_ok2 (M : sig end) : sig
>>>>
>>>> type t
>>>> module B : S with type t = t
>>>>
>>>> end = struct
>>>>
>>>> module T = struct end
>>>> module B = struct
>>>> include Make (T)
>>>> end
>>>> include B
>>>>
>>>> end
>>>>
>>>> module Make_bad (M : sig end) : sig
>>>>
>>>> type t
>>>> module C : S with type t = t
>>>>
>>>> end = struct
>>>>
>>>> module C = struct
>>>> module T = struct end
>>>> include Make (T)
>>>> end
>>>> include C
>>>>
>>>> end
>>>>
>>>> ========================================
>>>>
>>>> --
>>>> Carl Eastlund
>>
>> --
>> Caml-list mailing list. Subscription management and archives:
>> https://sympa.inria.fr/sympa/arc/caml-list
>> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
>> Bug reports: http://caml.inria.fr/bin/caml-bugs
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Caml-list] Weird type error involving 'include' and applicative functors
2015-02-19 18:21 ` Milan Stanojević
@ 2015-02-19 18:23 ` Milan Stanojević
0 siblings, 0 replies; 8+ messages in thread
From: Milan Stanojević @ 2015-02-19 18:23 UTC (permalink / raw)
To: Leo White; +Cc: Gabriel Scherer, Carl Eastlund, caml users
Oh, it seems Carl already did it. I'll mark mine as duplicate.
On Thu, Feb 19, 2015 at 1:21 PM, Milan Stanojević <milanst@gmail.com> wrote:
> I submitted a bug report.
> http://caml.inria.fr/mantis/view.php?id=6788
>
>
> On Tue, Feb 17, 2015 at 4:40 PM, Milan Stanojević <milanst@gmail.com> wrote:
>> It seems that type checker does know that C.T and T are aliases since
>> this compiles
>>
>> module C = struct
>> module T = struct end
>> include Make (T)
>> end
>> include C
>>
>> let f (x : Make(Make(T)).t) : Make(Make(C.T)).t = x
>>
>> Somehow the fact that C.T = T is lost when checking against the signature.
>>
>>
>>
>>
>> On Mon, Feb 16, 2015 at 1:03 PM, Leo White <lpw25@cam.ac.uk> wrote:
>>> Gabriel gives an accurate accout of what is going on. To me, it looks
>>> like the type-checker should probably accept this, so I would submit it
>>> as a bug (I suspect a missing call to Env.normalize_path somewhere, but
>>> perhaps there is something more significant going on here).
>>>
>>> Regards,
>>>
>>> Leo
>>>
>>> Gabriel Scherer <gabriel.scherer@gmail.com> writes:
>>>
>>>> That is one of the dark corners of the module system.
>>>>
>>>> I don't know whether an ideal type-checker should accept your last
>>>> definition or not. It is non-intuitive that some are accepted and
>>>> others rejected; some things in the module system are non-intuitive
>>>> for good reasons, some others because of implementation limitations,
>>>> and it's not always clear to non-experts which is which).˙But I can
>>>> explain why the last definition is harder for the type-checker to
>>>> accept than the other.
>>>>
>>>> # module A = struct
>>>> module T = struct end
>>>> module C = struct
>>>> include Make(T)
>>>> end
>>>> include C
>>>> end
>>>> ;;
>>>> module A :
>>>> sig
>>>> module T : sig end
>>>> module C : sig type t = Make(T).t end
>>>> type t = Make(T).t
>>>> end
>>>>
>>>> # module B = struct
>>>> module C = struct
>>>> module T = struct end
>>>> include Make(T)
>>>> end
>>>> include C
>>>> end
>>>> ;;
>>>> module B :
>>>> sig
>>>> module C : sig module T : sig end type t = Make(T).t end
>>>> module T = C.T
>>>> type t = Make(T).t
>>>> end
>>>>
>>>>
>>>> Note the important difference in the inferred signatures in both
>>>> cases. Both modules have
>>>> type t = Make(T).t
>>>> but, in the first case, this is the *same module T* that is mentioned
>>>> in the signature of T, while in the second case, there are two
>>>> different modules, C.T and T (the latter being generated by the
>>>> "include", with an equation that it is equal to the former).
>>>>
>>>> The reasoning to check against your signature
>>>> sig
>>>> type t
>>>> module C : S with type t = t
>>>> end
>>>> is thus more complicated in the second case: the type-checker would
>>>> need to use the equation (T = C.T) to check that indeed C.t is equal
>>>> to t.
>>>>
>>>> I think this is due to the rather contorted way you define C first in
>>>> the implementations and include it later, while in the signature first
>>>> define t and then C. Note that the following signature, which is
>>>> morally equivalent, accepts both implementations (and thus all the
>>>> functors in your file):
>>>> sig
>>>> module C : S
>>>> type t = C.t
>>>> end
>>>>
>>>>
>>>> On Fri, Feb 13, 2015 at 10:40 PM, Carl Eastlund
>>>> <ceastlund@janestreet.com> wrote:
>>>>> This seems to be a compiler bug, but let me know if I've missed something.
>>>>> The behavior I see is that Make_ok1 and Make_ok2 compile fine, but the very
>>>>> similar functor Make_bad does not. I get this compile error:
>>>>>
>>>>> ========================================
>>>>>
>>>>> Error: Signature mismatch:
>>>>> Modules do not match:
>>>>> sig
>>>>> module C : sig module T : sig end type t = Make(T).t end
>>>>> module T = C.T
>>>>> type t = Make(T).t
>>>>> end
>>>>> is not included in
>>>>> sig type t module C : sig type t = t end end
>>>>> In module C:
>>>>> Modules do not match:
>>>>> sig module T : sig end type t = Make(T).t end
>>>>> is not included in
>>>>> sig type t = C.t end
>>>>> In module C:
>>>>> Type declarations do not match:
>>>>> type t = Make(T).t
>>>>> is not included in
>>>>> type t = t
>>>>>
>>>>> ========================================
>>>>>
>>>>> And here is the code:
>>>>>
>>>>> ========================================
>>>>>
>>>>> module type S = sig type t end
>>>>> module Make (M : sig end) : S = struct type t end
>>>>>
>>>>> module Make_ok1 (M : sig end) : sig
>>>>>
>>>>> type t
>>>>> module A : S with type t = t
>>>>>
>>>>> end = struct
>>>>>
>>>>> module A = struct
>>>>> include Make (struct end)
>>>>> end
>>>>> include A
>>>>>
>>>>> end
>>>>>
>>>>> module Make_ok2 (M : sig end) : sig
>>>>>
>>>>> type t
>>>>> module B : S with type t = t
>>>>>
>>>>> end = struct
>>>>>
>>>>> module T = struct end
>>>>> module B = struct
>>>>> include Make (T)
>>>>> end
>>>>> include B
>>>>>
>>>>> end
>>>>>
>>>>> module Make_bad (M : sig end) : sig
>>>>>
>>>>> type t
>>>>> module C : S with type t = t
>>>>>
>>>>> end = struct
>>>>>
>>>>> module C = struct
>>>>> module T = struct end
>>>>> include Make (T)
>>>>> end
>>>>> include C
>>>>>
>>>>> end
>>>>>
>>>>> ========================================
>>>>>
>>>>> --
>>>>> Carl Eastlund
>>>
>>> --
>>> Caml-list mailing list. Subscription management and archives:
>>> https://sympa.inria.fr/sympa/arc/caml-list
>>> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
>>> Bug reports: http://caml.inria.fr/bin/caml-bugs
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Caml-list] Weird type error involving 'include' and applicative functors
2015-02-15 10:26 ` Gabriel Scherer
2015-02-16 18:03 ` Leo White
@ 2015-02-24 4:38 ` Jacques Garrigue
2015-02-24 5:54 ` Jacques Garrigue
1 sibling, 1 reply; 8+ messages in thread
From: Jacques Garrigue @ 2015-02-24 4:38 UTC (permalink / raw)
To: Gabriel Scherer; +Cc: Carl Eastlund, OCaml Mailing List
On 2015/02/15 19:26, Gabriel Scherer wrote:
>
> That is one of the dark corners of the module system.
[…]
> I think this is due to the rather contorted way you define C first in
> the implementations and include it later, while in the signature first
> define t and then C. Note that the following signature, which is
> morally equivalent, accepts both implementations (and thus all the
> functors in your file):
> sig
> module C : S
> type t = C.t
> end
This is indeed the gist of the problem. Matching against
sig
type t
module C : S with type t = t
end
introduces a kind of mutual recursion: C.t is defined as t in the enclosing
signature, but t is C.t in the internal one. As a result we get a kind of
double-vision problem. Namely, t inside the internal C is Make(T).t (with
T the one inside C), but in the enclosing signature, the t inside C
is Make(C.T).t. While logically the T inside C and C.T are the same module,
the typing rule in Leroy's paper do not say anything like that.
σ : {1,...,m} → {1,...,n} for all i ∈ {1,...,m}, E;D1;...;Dn ⊢ Dσ(i) <: Di′
---------------------------------------------------------------------------------------
E ⊢ sig D1;…;Dn end <: sig D1′ ;...;Dm′ end
The definition in the premise must match without extra equations.
Here module aliases do not help.
What could help would be to strengthen the definitions in the premise, so
that T would be converted to C.T. But I don't know whether this is sound
or not, since this is not part of the current theory.
Jacques Garrigue
> On Fri, Feb 13, 2015 at 10:40 PM, Carl Eastlund
> <ceastlund@janestreet.com> wrote:
>> This seems to be a compiler bug, but let me know if I've missed something.
>> The behavior I see is that Make_ok1 and Make_ok2 compile fine, but the very
>> similar functor Make_bad does not. I get this compile error:
>>
>> ========================================
>>
>> Error: Signature mismatch:
>> Modules do not match:
>> sig
>> module C : sig module T : sig end type t = Make(T).t end
>> module T = C.T
>> type t = Make(T).t
>> end
>> is not included in
>> sig type t module C : sig type t = t end end
>> In module C:
>> Modules do not match:
>> sig module T : sig end type t = Make(T).t end
>> is not included in
>> sig type t = C.t end
>> In module C:
>> Type declarations do not match:
>> type t = Make(T).t
>> is not included in
>> type t = t
>>
>> ========================================
>>
>> And here is the code:
>>
>> ========================================
>>
>> module type S = sig type t end
>> module Make (M : sig end) : S = struct type t end
>>
>> module Make_ok1 (M : sig end) : sig
>>
>> type t
>> module A : S with type t = t
>>
>> end = struct
>>
>> module A = struct
>> include Make (struct end)
>> end
>> include A
>>
>> end
>>
>> module Make_ok2 (M : sig end) : sig
>>
>> type t
>> module B : S with type t = t
>>
>> end = struct
>>
>> module T = struct end
>> module B = struct
>> include Make (T)
>> end
>> include B
>>
>> end
>>
>> module Make_bad (M : sig end) : sig
>>
>> type t
>> module C : S with type t = t
>>
>> end = struct
>>
>> module C = struct
>> module T = struct end
>> include Make (T)
>> end
>> include C
>>
>> end
>>
>> ========================================
>>
>> --
>> Carl Eastlund
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Caml-list] Weird type error involving 'include' and applicative functors
2015-02-24 4:38 ` Jacques Garrigue
@ 2015-02-24 5:54 ` Jacques Garrigue
0 siblings, 0 replies; 8+ messages in thread
From: Jacques Garrigue @ 2015-02-24 5:54 UTC (permalink / raw)
To: Gabriel Scherer; +Cc: Carl Eastlund, OCaml Mailing List
On 2015/02/24 13:38, Jacques Garrigue <garrigue@math.nagoya-u.ac.jp> wrote:
> While logically the T inside C and C.T are the same module,
> the typing rule in Leroy's paper do not say anything like that.
>
> σ : {1,...,m} → {1,...,n} for all i ∈ {1,...,m}, E;D1;...;Dn ⊢ Dσ(i) <: Di′
> ---------------------------------------------------------------------------------------
> E ⊢ sig D1;…;Dn end <: sig D1′ ;...;Dm′ end
>
> The definition in the premise must match without extra equations.
> Here module aliases do not help.
> What could help would be to strengthen the definitions in the premise, so
> that T would be converted to C.T. But I don't know whether this is sound
> or not, since this is not part of the current theory.
More precisely, OCaml actually does a bit more than this rule, as it
strengthens abstract types. However there is no such thing as strengthening
for module aliases, as this would require having both a signature and an
alias for the same module. Allowing that could help solve this problem, but
this is not fixing a bug, rather extending the theory.
Jacques Garrigue
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2015-02-24 5:54 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-02-13 21:40 [Caml-list] Weird type error involving 'include' and applicative functors Carl Eastlund
2015-02-15 10:26 ` Gabriel Scherer
2015-02-16 18:03 ` Leo White
2015-02-17 21:40 ` Milan Stanojević
2015-02-19 18:21 ` Milan Stanojević
2015-02-19 18:23 ` Milan Stanojević
2015-02-24 4:38 ` Jacques Garrigue
2015-02-24 5:54 ` Jacques Garrigue
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox