Ticket #3 (assigned enhancement)

Opened 6 years ago

Last modified 4 months ago

feature request: record types with partially exported fields

Reported by: avatariks Owned by: Fūzetsu
Priority: major Milestone: 2.15.0
Version: Keywords:
Cc: duncan, nogin

Description

attached (M1) is an example of a situation, where haddock hides all fields of a record, just because one field is hidden. The result is that the other field is not shown in the documentation as well, even though it is exported.

As an example for why hiding certain fields of a record might make sense, consider M2. There we export two functions for decomposing T: f and g, whereas f is a class function that can be used for other datatypes as well, and g is a function specific to T. The ugly fT function is hidden from the user.

I'd wish myself a haddock output in which T would be shown in record style, but there would be a blank instead of fT or maybe something like "<hidden>".

Change History

Changed 6 years ago by avatariks

Trac crashes when I try to add attachments, so I just list the files here:

M1.hs:

module M1 
(
  T(T, g)
) 
where

data T = T {
  fT :: T,
  g :: T
}

M2.hs

module M2 
(
  C(..),
  T(T, g)
) 
where

class C a where
  f :: a -> a

data T = T {
  fT :: T,
  g :: T
}

instance C T where
  f = fT

Changed 6 years ago by anonymous

  • priority changed from major to minor

Changed 5 years ago by duncan

  • cc duncan added
  • priority changed from minor to major

Resetting priority. This makes the difference between the technique being usable or not. If none of the fields get documented then nobody can decipher the api.

My example is the tar package. I have a tar Entry type which is a record with a number of fields. I want to export record selectors so that user can do things like:

(fileEntry name content) { fileMode = executableFileMode }

However I do not want clients to be able to construct an Entry directly. We provide emptyEntry with default fields to be overridden. This lets us add new fields and guarantee that no client will break because they cannot mis-use the constructor by doing something like:

Entry blah blah blah ...

ie use it directly and then break when I add a field.

However if I do not export the constructor then the API docs do not mention any of the fields. It becomes just:

data Entry
  Tar archive entry

So, how would we document a record where the constructor(s) are not exported. Well, when the constructor is exported it looks like:

data Entry
  Tar archive entry
Constructors
  Entry	
    filePath :: !TarPath	Path of the file or directory.
    fileMode :: !FileMode	UNIX file mode (file permissions).
    ... etc

So how about exactly the same but omit the Constructor name:

data Entry
  Tar archive entry
Constructors
    filePath :: !TarPath	Path of the file or directory.
    fileMode :: !FileMode	UNIX file mode (file permissions).
    ... etc

If there were multiple constructors then that's also ok, we can keep the blocks of record names together. Just omit the constructor name div.

Similarly if we do not export all record fields names, just omit that one from the listing. Rather than switching to positional constructor style as it does now.

For the synopsis it displays using Haskell syntax. Here it's harder to omit the constructor and have it look sane. Still we can probably just do it anyway. One of:

data Entry = {
  filePath :: !TarPath
  fileMode :: !FileMode
  ...
}
data Entry = _ {
  filePath :: !TarPath
  fileMode :: !FileMode
  ...
}

or

data Entry {
  filePath :: !TarPath
  fileMode :: !FileMode
  ...
}

Each generalises to multiple missing or exported alternative constructors:

data Entry {
  filePath :: !TarPath
  fileMode :: !FileMode
  ...
}
| {
   blah :: Whatever
}

Changed 5 years ago by nogin

  • cc nogin added

Similarly, if I have a record type where all fields are exported, but the constructor itself is not (so that invariants can be enforced by the API), Haddock omits the fields from the documentation. If instead of

Type(field1,field2)

in the export list, I use

Type,field1,field2

Haddock would, of course, include the fields in the documentation but now they look as arbitrary functions, not as fields, which misses the point.

Changed 4 months ago by Fūzetsu

  • owner changed from somebody to Fūzetsu
  • status changed from new to assigned
  • milestone set to 2.15.0

OK, clearly there's a use case for this.

I'll see what I can do for the next release although I fear that this might cause confusion. We'll see I guess.

Note: See TracTickets for help on using tickets.