Hi all,
TLDR: instead of removing module headers and using module documentation as an export specification, I’m in favour of a module header specifying exported symbols and a source code structure that can also serve as documentation.
I think people have some excellent remarks on how to declare exports and ways to handle comments. At the core of the discussion is the fact that the module header and the module documentation duplicate information about exported symbols. To solve this, we could remove the module header and use the module documentation as an export list. I agree with Max though, that using comments for such an important feature as exporting symbols from a module can be dangerous. It mixes documentation and the programming language itself in a weird way. I’d like to advocate to restructure the module documentation instead and direct an Elm source file to a playground or notebook, mixing documentation and code in an well defined way.
Often, I find myself trying to keep the order of types and functions that I specified in the module documentation, in sync with the order of functions in my source file. This also means replicating the section headers I introduced in the module documentation, to clearly separate different groups of symbols. I end up writing a source file like this:
```elm
module Test exposing (f, g, h)
{-|
General info.
# Section 1
Intro to these functions.
@doc f, g
# Section 2
@doc h
-}
-- Section 1 --
{-| Doc for f -}
f : …
{-| Doc for g -}
g : …
-- Section 2 --
{-| Doc for h -}
h : …
```
I’m wondering why we can’t unify the module documentation and the source itself, breaking up the file into sections that group similar things together. We could thus writing something like:
```elm
module Test exposing (f, g, h)
{-|
General info.
-}
{-| # Section 1
Intro to these functions.
-}
{-| Doc for f -}
f : …
{-| Doc for g -}
g : …
{-| # Section 2
-}
{-| Doc for h -}
h : …
```
This way the source file reflects the documentation structure and vice versa. Some pros:
* There is a explicit separation between comments and the programming language, but they are clearly intertwined in the source file.
* Information about which symbols to expose is not duplicated any more. The compiler should only check if every exposed symbol has an associated doc comment.
* Structure of the module documentation and your source file is not duplicated any more. Moving a symbol from one section to another will be mirrored in the generated documentation.
* The concept of a module is still apparent and will help people to signal the importance of using modules to hide type information.
* You can read a module top to bottom as you would do with the rendered documentation, using your editor to quickly jumpt to sections.
* Generated documentation on a website would have the same structure as your source file, but with rendered headings, bullet lists, highlighted code examples, and so on, but without the code.
* Markdown can be used everywhere: module documentation, section documentation, symbol documentation.
One neg:
* If you want to move or rename a file, you’ll still need to change the module name. (See below for some thoughts on this).
So, instead of removing the module header and using the module documentation as an export specification, I’m in favour of a module header specifying exported symbols and a source code structure that can also serve as documentation, akin literate programming.
At some point in the feature, we could extend this idea and make a playground / notebook based development environment, rendering the inline documentation together with the functions. This is what Apple currently does with its Swift Playgrounds and Mathematica already did for a long time. It would be a wonderful way to teach people Elm with step-by-step instructions!
## Other thoughts
### Removing the module header
This proposal could still be combined with the idea to remove the model header and thus the duplication of module name and file name. Therefore we should introduce a keyword like `export` (the opposite of `import`) or `expose` (resampling `exposing` in an import declaration) and annotate symbols with it as shown below.
```elm
{-|
General info.
-}
{-| # Section 1
Intro to these functions.
-}
{-| Doc for f -}
export
f : …
{-| Doc for g -}
export
g : …
{-| # Section 2
-}
{-| Doc for h -}
export
h : …
```
I think in the end this boils down to taste:
* Do you prefer a module header which tells the reader a module is declared, giving a summary of all exported symbols and overcome the duplication of module name and file name?
* Or do you prefer to start programming right away, assuming the file name as the module name and annotated every exported symbol with an extra keyword?
(Off course you could leave out the keyword and automatically export symbols containing associated documentation, but that would be quite subtile!)
### Local exports
A short note about internal exports (or the “third option”) Evan mentions in the Gist. Combining the above proposal of notebooks, removing the module header, and the idea of internal exports will need export modification keywords for types. These could be something like this:
* `export` ⇒ export only the type name, currently `TypeName` in the export list
* `export public` ⇒ export the type name and all its constructors, currently `TypeName(..)` in the export list
* `export internal` ⇒ export all the constructors internally in the package but only the type name to package users, proposed as `TypeName(..local..)` in Evan’s Gist (maybe use only parens as in `TypeName()`, or is this to subtile?)
### Doc comment symbol
I’m not sure any more about the `|` in `{-| -}`. I think the origin of it lies in Haskell (Haddock actually), which uses `{-|` to start a comment about a symbol *after* the comment and `{-^` for the symbol *before*. This distinction isn’t used in Elm. Maybe `{--` and `--}` are clearer and less intrusive? Bonus point: you can use multiple dashes to visually separate sections!
```elm
module Test exposing (f, g, h)
{--
General info.
--}
{------------------------------------------
# Section 1
Intro to these functions.
--}
{-- Doc for f --}
f : …
{-- Doc for g --}
g : …
{----------------------------------------
# Section 2
--}
{-- Doc for h --}
h : …
```