Commit ac978a9d authored by Michael Hanus 's avatar Michael Hanus
Browse files

Description of module system modified (for conformity with Haskell)

parent 2091db6b
% $Id: report.tex,v 1.2 1999/07/21 15:46:55 hanus Exp hanus $
% $Id: report.tex,v 1.3 1999/08/26 12:48:40 hanus Exp hanus $
% $Log: report.tex,v $
% Revision 1.3 1999/08/26 12:48:40 hanus
% Section about lambda lifting updated
%
% Revision 1.2 1999/07/21 15:46:55 hanus
% Section on lambda lifting transformation added
%
......@@ -551,6 +554,8 @@ definition of 0-ary local functions since a definition of the form
``\pr{where f = \ldots}'' is considered as the definition of
a local variable \pr{f} by this rule which is usually the intended
interpretation (see previous examples).
Appendix~\ref{app-lifting} contains a precise formalization
of the meaning of local definitions.
\subsection{Free Variables}
......@@ -1332,7 +1337,9 @@ $\Ac(\pr{cond}) = \forall \alpha.\pr{Constraint}\to \alpha \to \alpha$.
A \emph{program is well-typed}\index{well-typed}
if all its rules are well-typed with a unique assignment of
type schemes to defined functions.
type schemes to defined functions.\footnote{Here we assume
that all local declarations are eliminated by the transformations
described in Appendix~\ref{app-lifting}.}
Note that the following recursive definition is a well-typed
Curry program according to the definition above (and the type definitions
......@@ -1395,7 +1402,7 @@ If a program does not contain a module head, the \emph{standard module head}
\emph{Module names}\index{module name}\index{name!of a module}
can be given a hierarchical structure by inserting dots
which is useful if larger applications should be structured
into different subprojects, e.g.,
into different subprojects. For instance,
\startprog
company.project1.subproject2.mod4
\stopprog
......@@ -1403,13 +1410,15 @@ is a valid module name.
The dots may reflect the hierarchical file structure
where modules are stored. For instance, the module
\pr{compiler.symboltable} could be stored in the file
\pr{symboltable.cur} in the directory \pr{compiler}.
\pr{symboltable.curry} in the directory \pr{compiler}.
To avoid such long module names when referring to entities
of this module by qualification, imported modules can be renamed
by the use of ``\pr{as}'' in an import declaration (see below).
Without any further restrictions in the module head,
all entities which are directly accessible (see below) in the module
(roughly speaking, all entities defined or imported in the module)
are exported.
In order to restrict the set of exported entities of a module,
all entities which are defined by top-level declarations in this module
are exported (but not those entities that are imported into this module).
In order to modify this standard set of exported entities of a module,
an \emph{export list}\index{entity!exported}
\index{export declaration}\index{declaration!export}
can be added to the module head.
......@@ -1422,36 +1431,28 @@ and \pr{newStack}. An export list can contain the following entries:
\begin{enumerate}
\item
\emph{Names of datatypes}: This exports only the datatype, whose name
must be directly accessible in this module,
must be accessible in this module,
\emph{but not} the constructors of the datatype.
The export of a datatype
without its constructors allows the definition of
\emph{abstract datatypes}\index{abstract datatype}\index{datatype!abstract}.
\item
\emph{Datatypes with constructors}: If the export list contains
the entry \pr{t(c$_1$,\ldots,c$_n$)}, then \pr{t} must be a datatype
directly accessible in the module and \pr{c$_1$},\ldots,\pr{c$_n$}
are directly accessible constructors of this datatype. In this case,
the datatype \pr{t} and the constructors \pr{c$_1$},\ldots,\pr{c$_n$}
are exported by this module.
\item
\emph{Datatypes with all constructors}: If the export list contains
the entry \pr{t(..)}, then \pr{t} must be a datatype
whose name is directly accessible in the module. In this case,
whose name is in the module. In this case,
the datatype \pr{t} and all constructors of this datatype,
which must be also directly accessible in this module, are exported.
which must be also accessible in this module, are exported.
\item
\emph{Names of functions}: This exports the corresponding functions
whose names must be directly accessible
whose names must be accessible
in this module. The types occurring in the
argument and result type of this function are implicitly exported,
otherwise the function may not be applicable outside this module.
\item
\emph{Modules}: The set of all directly accessible
\emph{Modules}: The set of all accessible
entities imported from a module $m$
into the current module (see below)
can be exported by a single entry ``\pr{module $m$}''
......@@ -1463,28 +1464,32 @@ module queue(module stack, enqueue, dequeue) where \ldots
specifies that the module \pr{queue} exports the entities
\pr{stackType}, \pr{push}, \pr{pop}, \pr{newStack}, \pr{enqueue},
and \pr{dequeue}.
If the exported entities from imported modules should be further
restricted, one can also add an export list to the exported module.
This list can contain names of datatypes
and functions imported from this module. If a datatype which is imported
from another module is exported, the datatype is exported in the same way
(i.e., with or without constructors) how it is imported
into the current module. Thus, a further specification
for the exported constructors is not necessary.
For instance, the module head
\startprog
module queue(module stack(stackType,newStack), enqueue, dequeue) \ldots
\stopprog
specifies that the module \pr{queue} exports the entities
\pr{stackType} and \pr{newStack}, which are imported from \pr{stack},
and \pr{enqueue} and \pr{dequeue}, which are defined in \pr{queue}.
\end{enumerate}
%
The unqualified names of the exported entities of a module
must be pairwise different to avoid name clashes in the use of
these entities. For instance, the module
\startprog
module m(f,ma.g) where
import ma
f x = ma.g x
\stopprog
exports the names \pr{m.f} and \pr{m.g}, i.e., a \emph{qualified entity}
consists always of the name of the exported module followed by a dot
and the unqualified name of the entity (without spaces between the dot
and the names). If module \pr{ma} also exports the entity \pr{f},
then the export declaration
\startprog
module m(f,ma.f) where
import ma
f x = ma.f x
\stopprog
is not allowed since the exported name \pr{m.f} cannot be uniquely resolved.
All entities defined by top-level declarations in a module are
\emph{directly accessible}\index{directly accessible}\index{accessible!directly}
in this module. Additionally, the
entities exported by another module can be also made directly accessible
\emph{always accessible} in this module, i.e., there is no need
to qualify the names of top-level declarations. Additionally, the
entities exported by another module can be also made accessible
in the module by an \pr{import}%
\pindex{index}\index{entity!imported}%
\index{import declaration}\index{declaration!import}
......@@ -1504,19 +1509,24 @@ import family(father, grandfather)
\stopprog
imports only the entities \pr{father} and \pr{grandfather}
from the module \pr{family}, provided that they are exported
by \pr{family}.
by \pr{family}. Similarly to export declarations,
a datatype name \pr{t} in an import list imports only the
datatype without its constructors whereas the form \pr{t(..)}
imports the datatype together with all its constructors
(provided that they are also exported).
The names of all imported entities are directly accessible in the current
The names of all imported entities are accessible in the current
module, i.e., they are equivalent to top-level declarations,
provided that their names are not in conflict with other names.
For instance, if a function \pr{f} is imported from module \pr{m}
but the current module contains a top-level declaration for \pr{f}
(which is thus directly accessible in the current module),
the imported function is not directly accessible.
Similarly, if two identical names are imported from different modules,
none of these entities is directly accessible.
It is possible to access imported but not directly accessible
names by prefixing them with the module identifier.
the imported function is not accessible (without qualification).
Similarly, if two identical names are imported from different modules
and denote different entities,
none of these entities is accessible (without qualification).
It is possible to refer to such imported but not directly accessible
names by prefixing them with the module identifier (\emph{qualification}).
For instance, consider the module \pr{m1} defined by
\startprog
module m1 where
......@@ -1537,60 +1547,101 @@ import m2
\ldots
\stopprog
Then the names of the imported functions \pr{f} are not directly accessible
in the main module but one can refer by the qualified identifiers
\pr{m1.f} or \pr{m2.f}
to the corresponding imported entities. Note that export
declarations only allow unqualified names to be exported
(which is the reason for the direct accessibility condition
for the exports). This prevents hierarchical qualifications like
\pr{mod1.mod2.f} and supports the view to consider a module
as a single collection of related entities.
in the main module but one can refer
to the corresponding imported entities by the qualified identifiers
\pr{m1.f} or \pr{m2.f}.
Another method to resolve name conflicts between imported
entities is the renaming of imported entities.
For instance, the name conflict between \pr{m1.f} and \pr{m2.f}
can be resolved by
the following imports:
entities is the qualification of an imported module.
If we change the \pr{main} module to
\startprog
module main where
import m1
import m2 renaming f to m2_f
import qualified m1
import m2
\ldots
\stopprog
Thus, the entity \pr{f} exported by module \pr{m2} is imported
with the name \pr{m2_f}.
In the subsequent body of this module, the (directly accessible)
name \pr{f} refers to the entity exported by module \pr{m1}
and the (directly accessible) name
\pr{m2_f} refers to the entity \pr{f} exported by module \pr{m2}.
Only imported entities can be renamed, i.e., the import declaration
then the name \pr{f} refers to the entity \pr{m2.f} since all entities
imported from \pr{m1} are \emph{only accessible by qualification}
like \pr{m1.f}.
A further method to avoid name conflicts is the hiding
of imported entities. Consider the following definition:
\startprog
import m(f) renaming g to mg
module main where
import m1 hiding (f)
import m2
\ldots
\stopprog
will always cause an error.
The name \pr{f} in the \pr{main} module refers to the entity \pr{m2.f}
since the name \pr{f} is not imported from \pr{m1} by the hiding
declaration. The hiding clause effects only unqualified
names, i.e., the entity \pr{m1.f} is still accessible in the body
of the \pr{main} module. Therefore, a hiding clause has no effect
in combination with a \pr{qualified} import.
Similarly to export declarations, a datatype \pr{t} in a hiding
clause hides only the datatype (but not its constructors)
whereas the form \pr{t(..)} hides the complete datatype
including its constructors.
The effect of several \pr{import} declarations is cumulative,
i.e., if an entity is hidden in one import declaration,
it can still be imported by another import declaration.
For instance, if module \pr{mt} exports a datatype \pr{t}
together with its constructors, then the import declarations
\startprog
import mt hiding (t(..))
import mt (t)
\stopprog
imports all entities exported by \pr{mt} but
only the name \pr{t} of the datatype without its constructors,
since the first hiding clause imports everything from \pr{mt}
except the complete datatype \pr{t} and the second import
specification additionally imports the name of the datatype \pr{t}.
Imported modules can also be given a new local name
in the import declaration. For instance, the declaration
\startprog
import m(f) as foo
\stopprog
enables access to the name \pr{f} (provided that it is not in
conflict with another entity with the same name) and \pr{foo.f}
but not to \pr{m.f}. This local renaming enables the abbreviation
of long module names and the substitution of different modules
without changing the qualifiers inside a module.
Although each name refers to exactly one entity, it is possible
that the same entity is referred by different names.
For instance, consider the module \pr{m} defined by
For instance, consider the modules defined by
\startprog
module m(f) where
f :: Int -> Int
\ldots
\stopprog
and the module \pr{use_m} defined by
\startprog
module use_m(f) where
module m1(m.f) where
import m
\ldots
module m2(m.f) where
import m
\ldots
\stopprog
together with the main module
\startprog
module main where
import m renaming f to mf
import use_m
import m1
import m2
\ldots
\stopprog
Then the names \pr{mf} as well as \pr{f} refers in the main module
to the same function defined in module \pr{m}.
Now the names \pr{f}, \pr{m1.f}, and \pr{m2.f} refer to the
identical entity, namely the function \pr{f} defined in module \pr{m}.
Note that there is no need to qualify \pr{f} in the module \pr{main}
since this name is unambiguously resolved to the function \pr{f}
defined in module \pr{m}, although it is imported via two different
paths.
Qualified names are treated syntactically like unqualified
names. In particular, a qualified infix operator like \pr{Complex.+}
has the same fixity as the definition of \pr{+} in the module
\pr{Complex}, i.e., the expression ``\pr{x Complex.+ y}'' is
syntactically valid.
The import dependencies between modules must be \emph{non-circular},
i.e., it is not allowed that module $m_1$ imports module $m_2$
......@@ -2931,9 +2982,10 @@ or another identifier
The following symbols are \emph{keywords}\index{keywords}
and cannot be used as an identifier:
\startprog
choice data else external flex free if
import in infix infixl infixr let module
optmatch pragma renaming rigid then to where
as choice data else external flex free
hiding if import in infix infixl infixr
let module optmatch pragma qualified rigid then
where
\stopprog
%
The syntax leaves undefined \emph{Literal} of primitive types.
......@@ -3016,20 +3068,15 @@ end
end
\production Export
FunctionName
\por TypeConstrID
\por TypeConstrID \term{(} \seq{DataConstrID}{,}{n} \term{)}
\por TypeConstrID \term{(..)}
\por \term{module} ModuleID \opt{\term{(} \seq{FuncOrType}{,}{n} \term{)}}
end
\production FuncOrType
FunctionName $|$ TypeConstrID
QFunctionName
\por QTypeConstrID
\por QTypeConstrID \term{(..)}
\por \term{module} ModuleID
end
\production Block
\term{\{}
\opt{\seq{Import}{;}{n} \term{;}}
\opt{\seq{ImportDecl}{;}{n} \term{;}}
\marg{n \geqslant 0}
\next \phantom{\term{\{}}
\opt{\seq{Pragma}{;}{n} \term{;}}
......@@ -3043,17 +3090,20 @@ end
\marg{m \geqslant 0}
end
\production Import
\term{import} ModuleID \opt{\term{(} \seq{FuncOrType}{,}{n} \term{)}} \opt{Renamings}
\production ImportDecl
\term{import} \opt{\term{qualified}} ModuleID \opt{\term{as} ModuleID}
\opt{ImportRestr}
end
\production Renamings
\seq{Renaming}{}{n}
\production ImportRestr
\term{(} \seq{Import}{,}{n} \term{)}
\por \term{hiding} \term{(} \seq{Import}{,}{n} \term{)}
end
\production Renaming
\term{renaming} FunctionName \term{to} FunctionName
\por \term{renaming} TypeConstrID \term{to} TypeConstrID
\production Import
FunctionName
\por TypeConstrID
\por TypeConstrID \term{(..)}
end
\production Pragma
......@@ -3205,7 +3255,7 @@ end
\term{\ttbs} \seq{SimplePattern}{}{n} \term{->} Expr \marg{n > 0}
\por \term{let} LocalDefs \term{in} Expr
\por \term{if} Expr \term{then} Expr \term{else} Expr
\por Expr InfixOpID Expr
\por Expr QInfixOpID Expr
\por \term{-} Expr
\por FunctExpr
end
......@@ -3218,30 +3268,38 @@ end
QVariableID \marg{\mbox{\it variable}}
\por QDataConstrID \marg{\mbox{\it data constructor}}
\por QFunctionID \marg{\mbox{\it defined function}}
\por \term{(} InfixOpID \term{)} \marg{\mbox{\it operator function}}
\por \term{(} QInfixOpID \term{)} \marg{\mbox{\it operator function}}
\por Literal
\por \term{()} \marg{\mbox{\it empty tuple}}
\por \term{(} Expr \term{)} \marg{\mbox{\it parenthesized expression}}
\por \term{(} \seq{Expr}{,}{n} \term{)} \marg{\mbox{\it tuple, $n > 1$}}
\por \term{[} \seq{Expr}{,}{n} \term{]}\marg{\mbox{\it list, $n\geqslant 0$}}
\por \term{(} Expr InfixOpID \term{)} \marg{\mbox{\it left section}\index{section}\index{section!left}\index{left section}}
\por \term{(} InfixOpID Expr \term{)} \marg{\mbox{\it right section}\index{section}\index{section!right}\index{right section}}
\por \term{(} Expr QInfixOpID \term{)} \marg{\mbox{\it left section}\index{section}\index{section!left}\index{left section}}
\por \term{(} QInfixOpID Expr \term{)} \marg{\mbox{\it right section}\index{section}\index{section!right}\index{right section}}
end
\production QTypeConstrID
ModuleID \term{.} TypeConstrID $~|~$ TypeConstrID
\opt{ModuleID \term{.}} TypeConstrID
end
\production QDataConstrID
ModuleID \term{.} DataConstrID $~|~$ DataConstrID
\opt{ModuleID \term{.}} DataConstrID
end
\production QFunctionName
\term{(} QInfixOpID \term{)} $|$ QFunctionID
end
\production QInfixOpID
\opt{ModuleID \term{.}} InfixOpID
end
\production QFunctionID
ModuleID \term{.} FunctionID $~|~$ FunctionID
\opt{ModuleID \term{.}} FunctionID
end
\production QVariableID
ModuleID \term{.} VariableID $~|~$ VariableID
\opt{ModuleID \term{.}} VariableID
end
\production Literal
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment