wiki:ModuleSystem

Version 18 (modified by simonmar@…, 8 years ago) (diff)

--

Module System oddities

There are inconsistencies in the current module system that cause confusion for users and complications for implementors. The issue is that while import, export, and hiding declarations have the same syntax, they have slightly different interpretations when it comes to names in the typespace.

In particular capital names are treated as types or classes in imports and exports but are treated as types, classes or value constructors in hiding clauses and there is no way to export just a constructor if it has the same name as a type.

Proposal

Make bare capital names _always_ refer to value constructors, the presence of a subordinate list will mean it should be interpreted as a type or class.

so T will refer to a constructor always and T() will refer to a class or type always.

this same rule will be used uniformly in export,import, and hiding lists.

This will not only make everything consistant, but allow seperate decisions on whether to export a value or type constructor if they have the same name.

elements within a subordinate list will be intpreted as before, as either data constructors, class methods, or field names.

see section 9 of the following paper for more details:

reference:

Clarifications

There are a few things that should probably be clarified by the language definition dealing with field names and class methods, not that there is debate but they should be clearly specified:

  • does exporting a class name and a method name seperately as a function allow it to be declared in instance declarations? or does the function name need to be exported as part of a subordinate list?
  • the field name and function namespaces are different and export/import rules should take this into account, declaring fields creates _both_ a function and a field name. so should exporting the function also export the field name? or should the field name only be exportable via a subordinate list?

Some compilers distinguish these namespaces, others do not.

  • We also may wish to specify recursive module behavior now that the work at formalizing the rules has been done in the previous paper. jhc and helium both implement the algorithm as given to good effect.

Alternative proposal

There has been past discussion on mailing lists about clarifying the import/export namespace in a different way. Each type or class constructor in an import or export list could be annotated with its namespace, e.g.

  • import Foo (class Foo (Foo,Bar), data Baz())

I believe this would solve the same problems as the above proposal, but would be much less backward-compatible.

Permit Signatures in Export Lists

There is a good case to be made for permitting the inclusion of function signatures in the export list of a module. People often write them there anyway in comments, but the comments are not checked against the implementation, so changes can go unnoticed. There is also a good software engineering principle that says you should specify your interfaces as fully as possible. Signatures in export lists should be considered equivalant to signatures specified in the module itself at the top level for all purposes. If there are signatures in both the interface and the implementation, they should be identical (not just unifiable).

If we /required/ signatures in export lists (and always required a full export list too), this would solve the recursive module problem for some compilers very simply. The export list would represent exactly the information currently contained in ghc's hs-boot files (and nhc98's hand-written .hi bootstrapping method). Other compilers such as jhc and helium have no problem with recursive modules as is.

Permit qualified exports

There was a long thread about this on the libraries list. Details to be filled in here. Outline:

  • module GTK (..., qualified module GTK.Button as Button, ...) where

The user can import GTK and get all of the contents of GTK.Button imported qualified as Button.

There's a semi-concrete proposal to support this in the context of the existing Haskell 98 module system spec, here: http://www.haskell.org/pipermail/libraries/2005-March/003420.html. See the archives of the libraries list for the discussion leading up to that.

Permit 'hiding' in export lists

Example:

  • module Foo ( module Bar hiding (baz), Foo.baz ) where