Browse thread
Type visibility limitation in recursive modules
[
Home
]
[ Index:
by date
|
by threads
]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
| Date: | -- (:) |
| From: | Márk_S._Zoltán <zoltan.s.mark@d...> |
| Subject: | Re: [Caml-list] Type visibility limitation in recursive modules |
The problem only impacts types declared via parametrized type
constructors. To wit:
This does not work:
----------------------------------------
module rec Aleph : sig type t = Tag of Beth.t end =
struct type t = Tag of Beth.t end
and Beth : sig type t val v : Aleph.t end =
struct type t = Aleph.t list let v = Aleph.Tag([]) end
This does:
----------------------------------------
module rec Aleph : sig type t = Tag of Beth.t end =
struct type t = Tag of Beth.t end
and Beth : sig type t val v : Aleph.t end =
struct type t = Nil | Cons of Aleph.t * t let v = Aleph.Tag(Nil) end
And this does not:
----------------------------------------
type 'a mylist = Nil | Cons of 'a * 'a mylist
module rec Aleph : sig type t = Tag of Beth.t end =
struct type t = Tag of Beth.t end
and Beth : sig type t val v : Aleph.t end =
struct type t = Aleph.t mylist let v = Aleph.Tag(Nil) end
I have spent a few (dozen) hours debugging the compiler, and came to the
conclusion that the reason for this bug is that "strenghtening" does not
take place for Tconstr's. Tconstr types use their type_manifest fields
to hold a description of the type, while Tvariant types set it to None.
When the typing process of recursive modules reaches the strenghtening
phase, it dutifully avoids updating Tconstr's because their
type_manifest matches Some _, not None. As a result, Tconstr type
implementations cannot be hidden inside a recursive module.
This issue has other interesting variations, e.g. this works:
-----------------------------------------------
module type AT = sig type t val v : t end
module type S = sig module Aleph : AT end
module Make = functor(A : AT) ->
(struct module Aleph = A end : S with module Aleph = A)
module rec Al : AT =
struct type t = string let v = "v" end
and Ex : S with module Aleph = Al = Make(Al)
This doesn't:
-----------------------------------------------
module type AT = sig type t val v : t end
module type S = sig module Aleph : AT end
module Make = functor(A : AT) ->
(struct module Aleph = A end : S with module Aleph = A)
module rec Al : sig type t val v : t end (* NB: AT!!! *) =
struct type t = string let v = "v" end
and Ex : S with module Aleph = Al = Make(Al)
-----------------------------------------------------
File "Anomaly.ml", line 34, characters 9-33:
In this `with' constraint, the new definition of Aleph
does not match its original definition in the constrained signature:
Modules do not match: sig type t = Al.t end is not included in AT
The field `v' is required but not provided
----------------------------------------------------
Cheers
Z-