haskell / haddock

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

Declarations with standalone kind signatures are rendered without kinds #1178

Open RyanGlScott opened 4 years ago

RyanGlScott commented 4 years ago

If I run this code through Haddock 2.24.0:

{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE StandaloneKindSignatures #-}
module Foo where

type Comp :: (b -> c) -> (a -> b) -> (a -> c)
type Comp f g x = f (g x)

This is how it is rendered:

haddock

This is a bit of a shame, as Haddock completely loses the kind information associated with the standalone kind signature. For a more elaborate example of where this happens, see the Hackage documentation for singletons-2.7 (example).

I can see two possible solutions:

  1. Render standalone kind signatures in Haddock. This would be a rather large undertaking, and there are several design considerations that I'm not sure about.
  2. When processing a declaration with a standalone kind signature, then render it as if it had been written using inline kind annotations. In other words, render Comp above like this instead:

    haddock

    This is arguably somewhat hackier, but it accomplishes the goal of displaying the kind information without having to support rendering standalone kind signatures in full.

RyanGlScott commented 4 years ago

Solution (2) would have to be implemented carefully. Here is a tricky corner case:

{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE StandaloneKindSignatures #-}
module Foo where

import Data.Kind

type D :: (j -> Type) -> (j -> Type) -> Type
data D (f :: k -> Type) g = forall (a :: k). MkD (f a) (g a)

How should data D be rendered? It has both a standalone kind signature and inline kind information. Here are two incorrect ways to render it:

The only sensible ways to render D would be one of the following:

Either option would require at least one kind substitution. It's not clear to me if one option would be easier to implement than the other.

RyanGlScott commented 4 years ago

See goldfirere/singletons#466 for an example of where this limitation occurs "in practice". In particular, https://github.com/goldfirere/singletons/issues/466#issuecomment-646117067 contains a laundry list of obstacles that I ran into when trying to implement option (1) from https://github.com/haskell/haddock/issues/1178#issuecomment-619226962.

vdukhovni commented 2 years ago

Reading over the previous comments, it seems to me that (1) is the only plausible path forward, along the lines of https://github.com/goldfirere/singletons/issues/466 with boring kind signatures elided. If the kind and the type are always presented together there'd be no need for a separate namespace to refer to the kind signature. As for documentation, of both the SAKS and the type declaration have haddock comments, present both, with wherever the type definition appears in the docs. I don't think there's a way to export just a kind signature without a definition, so the definition controls the placement of the text.

This just came up in MR 6969 where Compare a b was missing the kind signature that gave it proper context...