haskell / haddock

Haskell Documentation Tool
www.haskell.org/haddock/
BSD 2-Clause "Simplified" License
361 stars 241 forks source link

Explicit foralls are shown even if they don't matter #1271

Open jnbooth opened 3 years ago

jnbooth commented 3 years ago

Explicit foralls should only be displayed if they declare type parameters out of order. Haddock correctly displays the full type signature of this function:

f :: forall b a. a -> b

Here, the explicit forall should be displayed, because the out-of-order type parameters impact TypeApplications. However, Haddock also displays the full type signature of this function:

f :: forall a b. a -> b

Here, the explicit forall has no impact on users. It is an implementation detail. If a function is altered internally to use scoped type variables, or altered to no longer use them, those changes have no external effect and should be hidden from documentation. Therefore, Haddock should display this type signature instead:

f :: a -> b
Kleidukos commented 3 years ago

@jnbooth I'm going to need some more context one that one. Are you talking about about a situation with ExplicitForalls, ScopedTypeVariables, LiberalTypeSynonyms, RankNTypes or ExistentialQuantification are enabled?

jnbooth commented 3 years ago

Anywhere the "forall" keyword is used in a signature, which only requires enabling ExplicitForAll.

harpocrates commented 3 years ago

Just wanted to chime in an say I strongly support this. Except sometimes for type variable names, I am of the opinion Haddock should display a normalized version of the type signature. For instance, I would also hope forall (a :: Type) (b :: Type -> Type). a -> b a would display as a -> b a. The details get tricky, but I think a believe of this was done for Hi Haddock and even mostly merged in, just in an alternate codepath (keep reading for more on that codepath).

The current behaviour is to show the declaration as it was written in the Haskell source (redundant forall's and all), except in a handful of scenarios where the type signature is unavailable. In that case, an alternate code path is used to reify a Haskell type signature from the internal GHC type. If we made all types go through the second codepath (and didn't pay attention to the declarations as written in the Haskell source), I think we'd accomplish what this issue is about. Some people might complain that they can't force Haddock to show or not show a forall or kind signature though...

Kleidukos commented 3 years ago

I must admit I am a bit wary of tweaking the output of a user-provided signature without it being opt-in.

UX-wise, this could translate to an option that would display those instead of the user-provided signatures.

Note that I'm fully open to hear about the benefits of the feature, but it also means we give less control to the library maintainers about one the most critical bits of info that is generated by Haddock, and I don't know how this can backfire.

Right now, my opinion is the following: We can implement this feature, but keep it opt-in. This will allow us to iterate on it based on user feedback. Then in one or two versions, if it is widely accepted and liked, we can have "graduated" and the original signatures not shown by default instead.

meooow25 commented 6 months ago

Hi, I would like it if this were implemented (opt-in is also fine).

I have situations where using ScopedTypeVariables would allow me to help GHC with type inference, which necessarily includes adding explicit foralls, which clutters the Haddocks.

bar :: forall a. Bar a -> a
bar = coerce (foo @a)

I do not wish to keep the foralls in the Haddocks in such cases. It is awkward the that documented signature of the function has to change because I want to implement the body in a certain way.