Version française
Home     About     Download     Resources     Contact us    
Browse thread
Type visibility limitation in recursive modules
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ 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-