RFC: hyperlinks in Haddock docs

I'm making some changes to the way Haddock creates links, and I'd like to solicit comments on possible alternatives. The existing approach is for each non-locally-defined identifier in the current module, we hyperlink to a module that it was imported from, and that (a) actually documents the identifer, and (b) isn't hidden. There are some problems with the existing approach. It doesn't cope well with instances: instances might refer to types/classes not below the current module in the hierarchy. Also you might import an entity from a "hidden" module, but actually want to hyperlink to another module in the hierarchy, not below the current one. Hyperlinking in the documentation doesn't follow the module import hierarchy, and nor should it. So the new approach is to try to build up a global table of the "best" destinations to link to for each entity. The question is how to determine "best". Here's my first stab: - A is better than B if A directly or indirectly imports B But this isn't quite good enough: for example the Prelude re-exports a lot of stuff, but when linking Maybe for example, we probably want to link to Data.Maybe.Maybe rather than Prelude.Maybe. But the Prelude is the right place to get Int and String from. I don't particularly want the programmer to have to say for each entity where the best place to get it from is, much better would be to have a per-module flag that says "this module is a good/bad link destination". Perhaps we actually want to give an integer priority in each module. Thoughts? Better ideas? Cheers, Simon

On Tue, Feb 01, 2005 at 11:02:45AM -0000, Simon Marlow wrote:
I'm making some changes to the way Haddock creates links, and I'd like to solicit comments on possible alternatives.
The existing approach is for each non-locally-defined identifier in the current module, we hyperlink to a module that it was imported from, and that (a) actually documents the identifer, and (b) isn't hidden.
[...]
So the new approach is to try to build up a global table of the "best" destinations to link to for each entity. The question is how to determine "best". Here's my first stab:
- A is better than B if A directly or indirectly imports B
Perhaps it should be the other way round: the lowest non-hidden module that exports the name (if more than one such, fix on one). This would need most of GHC.* hidden, which is desirable anyway.

"Simon Marlow"
There are some problems with the existing approach. It doesn't cope well with instances: instances might refer to types/classes not below the current module in the hierarchy. Also you might import an entity from a "hidden" module, but actually want to hyperlink to another module
Thoughts? Better ideas?
If it turns out to be difficult to determine where to link, one option could be to link to a separate table on the same page, listing the candidates? -kzm -- If I haven't seen further, it is by standing in the footprints of giants

On Tue, Feb 01, 2005 at 11:02:45AM -0000, Simon Marlow wrote:
So the new approach is to try to build up a global table of the "best" destinations to link to for each entity.
Having a canonical home location for each entity might also help with another bugbear with Haddock: determining whether two unqualified names refer to the same entity. This is impossible at present because Haddock doesn't show qualified names (because doing so would be too cumbersome) and anyway the defining module is often hidden. It's not clear which of the documented catch functions are Control.Cuncurrent.catch, and which are System.IOError.catch. With the new scheme, documentation for an entity in a module other than its home could include a cross-reference to its home.

On Tue, 2005-02-01 at 11:02 +0000, Simon Marlow wrote:
I'm making some changes to the way Haddock creates links, and I'd like to solicit comments on possible alternatives.
The existing approach is for each non-locally-defined identifier in the current module, we hyperlink to a module that it was imported from, and that (a) actually documents the identifer, and (b) isn't hidden.
There are some problems with the existing approach. It doesn't cope well with instances: instances might refer to types/classes not below the current module in the hierarchy. Also you might import an entity from a "hidden" module, but actually want to hyperlink to another module in the hierarchy, not below the current one. Hyperlinking in the documentation doesn't follow the module import hierarchy, and nor should it.
So the new approach is to try to build up a global table of the "best" destinations to link to for each entity. The question is how to determine "best". Here's my first stab:
[snip]
Thoughts? Better ideas?
Let me throw in another example: In gtk2hs we have one huge module which defines all the types (this is produced by a code generator from a text file which describes the Gtk+ class hierarchy). However we don't ever want this module to be exposed to users. We re-export each data type corresponding to the Gtk+ class in it's one module (which wraps all the methods of the class). Eg the module Graphics.UI.Gtk.Buttons.Button re-exports 'Button' from the module Graphics.UI.Gtk.Types. So in other modules we say 'Button' for example but this gets linked to the huge hierarchy module rather than the re-export from the button module. So we have taken to linking to the module itself, ie using "Button" however this is no longer a nice solution now that we are using hierarchical modules names since we have to say "Graphics.UI.Gtk.Buttons.Button" which no longer flows very well in the middle of a sentence. The difficulty with this example is that our source module which contains a reference 'Buttton' does not actually import the module through which it is re-exported (indeed if we consistently did this I think we would get cyclic module deps). As an aside: we have not been able to get any of the module attributes #hide, prune, ignore-exports to work as described: http://www.haskell.org/haddock/docs/module-attributes.html So we would be happy to add some haddock declarations saying "do not link here!" or "please link here". For example we would say #hide in Graphics.UI.Gtk.Types (and we'd want that to mean never ever generate links to this module) and in each module that re-exports (and documents) each Gtk+ class add a haddock declarations saying "for references to X please always link to its definition here". Duncan

On Tue, Feb 22, 2005 at 05:45:39PM +0000, Duncan Coutts wrote:
In gtk2hs we have one huge module which defines all the types (this is produced by a code generator from a text file which describes the Gtk+ class hierarchy). However we don't ever want this module to be exposed to users. We re-export each data type corresponding to the Gtk+ class in it's one module (which wraps all the methods of the class). Eg the module Graphics.UI.Gtk.Buttons.Button re-exports 'Button' from the module Graphics.UI.Gtk.Types. [...] For example we would say #hide in Graphics.UI.Gtk.Types (and we'd want that to mean never ever generate links to this module) and in each module that re-exports (and documents) each Gtk+ class add a haddock declarations saying "for references to X please always link to its definition here".
The new Haddock is enormously better at this -- it does take #hide to imply that. If you can get the #hide attribute working in Graphics.UI.Gtk.Types, Haddock will redirect links to the lowest unhidden module that exports the name (whether imported by this one or not), which is exactly what you want. There's no need for qualified names or further declarations.

On Tue, 2005-02-22 at 19:10 +0000, Ross Paterson wrote:
On Tue, Feb 22, 2005 at 05:45:39PM +0000, Duncan Coutts wrote:
In gtk2hs we have one huge module which defines all the types (this is produced by a code generator from a text file which describes the Gtk+ class hierarchy). However we don't ever want this module to be exposed to users. We re-export each data type corresponding to the Gtk+ class in it's one module (which wraps all the methods of the class). Eg the module Graphics.UI.Gtk.Buttons.Button re-exports 'Button' from the module Graphics.UI.Gtk.Types. [...] For example we would say #hide in Graphics.UI.Gtk.Types (and we'd want that to mean never ever generate links to this module) and in each module that re-exports (and documents) each Gtk+ class add a haddock declarations saying "for references to X please always link to its definition here".
The new Haddock is enormously better at this -- it does take #hide to imply that. If you can get the #hide attribute working in Graphics.UI.Gtk.Types, Haddock will redirect links to the lowest unhidden module that exports the name (whether imported by this one or not), which is exactly what you want. There's no need for qualified names or further declarations.
Excellent! Thanks a lot. Any hint as to when the next Haddock release will be? Duncan
participants (5)
-
Duncan Coutts
-
Ketil Malde
-
Ross Paterson
-
ross@soi.city.ac.uk
-
Simon Marlow