packages feed

HaRe-0.6: tools/base/Modules/NamesEntities.lhs

Names and Entities
==================
\label{NameEnt}

Having described the Haskell module system as a mechanism for
namespace management, it is natural for us to begin its
specification with a discussion about names and entities.

> module NamesEntities (
>   module NamesEntities,
>   module Ents,
>   module Names
> ) where
>
> --import Set
> import Maybe(isJust)
> import Ents(Entity,isCon,isValue,owns)
> import Names(Name,QName,ModName,
>              getQualified, getQualifier, mkQual, mkUnqual)



Entities
--------

The basic idea is that _names_ in a program refer to _entities_.
Entities get introduced in a program by _declarations_.  For example,
a declaration such as #f x = x + 2# will introduce one entity:
a function named #f#. For the purposes of this paper, we are only interested in
top level entities, as they are manipulated by the module system.
There are at least six varieties of entities in Haskell:
functions, type constructors, value constructors, field labels, classes,
and class methods.  One could perhaps also consider class instances 
to be entities as they are also introduced by declarations.
We do not do that here because, in Haskell 98, there is no way to 
refer to them by name.

The module system specification is parametrized by the type of entities,
so we represent it using an abstract data type:

| data Entity = ... 
| isCon :: Entity -> Bool
| owns  :: Entity -> Set Entity 
|
| instance Ord Entity where ...

The function #isCon# is intended to distinguish between value constructors and
other entities, as they need to be handled differently in 
``hiding'' imports as opposed to normal imports and exports 
(see Section \ref{Sem}).

The function #owns# defines the _subordinate_ relation between entities.
Type constructors ``own'' their value constructors and field labels;
classes ``own'' their methods.

The requirement that entities are in the #Ord# class is stronger than
strictly necessary.  For the module system to work, we only need an equality
operation.  The ordering is required by the implementation of relations
as sets (described in Section \ref{sec-relations}).  

Entities will be written in a different font, and annotated with the 
module where they were originally defined.   
For example \ent{f}{M} refers to the entity #f# originally defined in 
module #M#.



Names
-----

Our specification is also parameterized by the types used to model names.
We distinguish between three different kinds of names:
    * _simple names_ (of type #Name#) are used in
      declarations, and to name entities exported by a module.
    * _program identifiers_ (whose type is #QName#) are used in the main
      text of the program and refer to entities.  They may be either qualified
      or unqualified.
    * _module names_ and _name qualifiers_ (with type #ModName#) are used to 
      name modules, in import declarations, in export lists, and in 
      qualified names.
We use the type #Name# whenever we want to indicate that only simple (i.e. not 
qualified) names are allowed, and #QName# when both simple and qualified names
may be used.  As for entities, the module system only needs equality operations
on names, but to use the #Set# data structure we require the #Ord# instance.

| data Name     = ...
| data ModName  = ...
| data QName    = ...
|
| getQualifier  :: QName -> Maybe ModName
| getQualified  :: QName -> Name
| mkUnqual      :: Name -> QName
| mkQual        :: ModName -> Name -> QName
|
| instance Ord Name where ...
| instance Ord ModName where ...
| instance Ord QName where ...

We define a couple of useful functions to manipulate (possibly qualified) names.
We note that if #qual# is applied to an already qualified name, it will
replace the old qualifier (however in this specification we always apply it
to unqualified names).

> isQual :: QName -> Bool
> isQual = isJust . getQualifier

> qual :: ModName -> QName -> QName
> qual m = mkQual m . getQualified 

It is also convenient to define an overloaded function #toSimple#,
which produces the unqualified part of a name.  It does nothing
on values of type #Name# as they cannot be qualified.  For values of
type #QName# it strips the qualifiers.

> class ToSimple t where
>   toSimple :: t -> Name
>
> instance ToSimple Name where
>   toSimple = id
>
> instance ToSimple QName where
>   toSimple = getQualified

In examples throughout the paper we shall use #String# for #Name#, #ModName#, 
and #QName#.  This is not the case in our prototype implementation, as
it defeats the purpose of having three different types in the first place.  
We made this choice to keep the examples readable.