Personal tools

No export lists

From HaskellWiki

(Difference between revisions)
Jump to: navigation, search
m (initialized)
 
(modula3.org)
 
(3 intermediate revisions by one user not shown)
Line 1: Line 1:
==No export lists==
 
 
 
Here I argue to remove export lists in Haskell in the long term and
 
Here I argue to remove export lists in Haskell in the long term and
 
replace them by locally defined export modes.
 
replace them by locally defined export modes.
Line 38: Line 36:
 
You can compare the export list
 
You can compare the export list
 
with the definition modules of [http://www.modula2.org/ Modula-2]
 
with the definition modules of [http://www.modula2.org/ Modula-2]
or the interface modules of [http://www.m3.org/ Modula-3],
+
or the interface modules of [http://www.modula3.org/ Modula-3],
 
and the module body with the implementation modules of the Modula dialects.
 
and the module body with the implementation modules of the Modula dialects.
   
Line 136: Line 134:
 
Cute, isn't it?
 
Cute, isn't it?
   
[[Category:Syntax]] [[Category:Proposal]]
+
Identifiers that are only re-exported
  +
(that is, imported from another module and exported as they are),
  +
may get a star attached in the import list,
  +
since this is the way, how the come into the module.
  +
Currently it is possible to import a bunch of identifiers anonymously by
  +
<haskell>
  +
import A
  +
import B
  +
</haskell>
  +
and export them explicitly
  +
<haskell>
  +
module Important (foo, bar) where ...
  +
</haskell>
  +
This way it is not clear, where <hask>foo</hask> and <hask>bar</hask> are from.
  +
With the new syntax this is no longer the case.
  +
<haskell>
  +
module Important where
  +
  +
import A(foo*)
  +
import B(bar*)
  +
</haskell>
  +
  +
  +
[[Category:Syntax]]
  +
[[Category:Proposals]]

Latest revision as of 06:39, 29 November 2007

Here I argue to remove export lists in Haskell in the long term and replace them by locally defined export modes. In the middle term both export declaration types could coexist.

[edit] 1 Status quo

In Haskell 98 modules, all declared identifiers are exported by default.

module Important where
 
-- automatically exported
foo :: Int
foo = 2
That is, other modules can import and use identifiers like
foo
.

You have finer control by export lists. They enable you to keep implementation details private and prevent users of the module from relying on interna that might change in future.

module Important (foo, Number(One,Two,Three)) where
 
-- manually exported
foo :: Int
foo = 2
 
data Number = -- type is exported
     Zero  -- heretical things kept private
   | One   -- public
   | Two   -- public
   | Three -- public
   | Many  -- private

You can compare the export list with the definition modules of Modula-2 or the interface modules of Modula-3, and the module body with the implementation modules of the Modula dialects.

Even more, the documentation extraction tool Haddock allows to divide a module into sections, and it allows this to do it either in the module body

module Important (foo, Number(One,Two,Three)) where
 
{- * Important functions -}
 
{- | most important function -}
foo :: Int
foo = 2
 
{- * Important data types -}
 
{- | most important data type -}
data Number =
     Zero
   | One
   | Two
   | Three
   | Many

or in the export list.

module Important (
   {- * Important functions -}
   foo,
 
   {- * Important data types -}
   Number(One,Two,Three)) where
 
 
{- | most important function -}
foo :: Int
foo = 2
 
{- | most important data type -}
data Number =
     Zero
   | One
   | Two
   | Three
   | Many

[edit] 2 Problems

The problem is that the export list duplicates data and the redundant information must be maintained. Whenever you add, remove, change the name of a function, you have to apply this change on the export list. If you comment out a malicious part of a module to get the rest compiled, you have to comment out parts of the export list, too. Haddock gives you the choice whether to define sections in the export list or the module body. However, what is the right choice?


[edit] 3 Solutions

The language Oberon, the successor of Modula-2 by Niklaus Wirth, goes a different way. Like Haskell, Oberon has only one file per module. The interface file for a module is extracted by the Oberon compiler from the module file. Whether an identifier is exported is defined right at the declaration of that identifier by an asterisk. Adapted to Haskell this would look like

module Important where
 
{- * Important functions -}
 
{- | most important function -}
foo* :: Int
foo = 2
 
{- * Important data types -}
 
{- | most important data type -}
data Number* =
     Zero
   | One*
   | Two*
   | Three*
   | Many

Whenever you define a new identifier, you can decide on exporting just where the cursor is. The reader sees whether an identifier is exported just where it is introduced. Every change including deletion of a declaration automatically alters the exported data. Cute, isn't it?

Identifiers that are only re-exported (that is, imported from another module and exported as they are), may get a star attached in the import list, since this is the way, how the come into the module. Currently it is possible to import a bunch of identifiers anonymously by

import A
import B

and export them explicitly

module Important (foo, bar) where ...
This way it is not clear, where
foo
and
bar
are from.

With the new syntax this is no longer the case.

module Important where
 
import A(foo*)
import B(bar*)