Skip to content
This repository was archived by the owner on Aug 3, 2024. It is now read-only.

Conversation

harpocrates
Copy link
Collaborator

This adds a module level Haddock option called print-runtime-reps which behaves like the GHC -fprint-explicit-runtime-reps flag. Hopefully this will let us restore beginner-friendliness to the Prelude types, without having to compromise for simplified types in GHC.Prim.

See the discussion in #838 for more.

This means all 'RuntimeRep' tyvars will be muted, unless the
user explicitly asks that they be shown by speciying

    {-# OPTIONS_HADDOCK print-runtime-reps #-}

This design is going make it possible to have the same type be
displayed differently depending on which module it is exported from
(eg. the Prelude or GHC.Exts).
@harpocrates
Copy link
Collaborator Author

We'll have to remember to add {-# OPTIONS_HADDOCK print-runtime-reps #-} to the top of some of the internal files of base once Hi Haddock is merged.


Here is what the test cases look like.

screen shot 2018-09-17 at 8 43 22 am

screen shot 2018-09-17 at 8 43 12 am

Copy link
Member

@RyanGlScott RyanGlScott left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks quite reasonable to me.

I forget: is there a users' guide description of all the flags that Haddock accepts? If so, it would be worth mentioning this flag in there as well.

Some minor comments inline.

| tv `elemVarEnv` subs
= TyConApp liftedRepDataConTyCon []
| otherwise
= TyVarTy (updateTyVarKind (go subs) tv)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's unnecessary to recurse into tv's kind here. (At least, IfaceType.defaultRuntimeRepVars doesn't do this.)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is necessary, since we do recurse into type variable's kinds when computing the inferred order of type variables (in tyCoFVsBndr'). Perhaps we should not recurse into the type variables kind there?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Upon further thought, maybe it's better if we do recurse here.

For pretty-printing purposes, it's probably overkill, since if you have a type like:

forall (r :: RuntimeRep) (a :: TYPE r). Int -> a

Then after defaulting, it'll still display as:

forall a. Int -> a

Regardless of whether you recurse into the kind of a (in Int -> a) or not. On the other hand, if you don't recurse into the kind of a, then you have a strange situation where the kind of a in forall a is Type, but the kind of a in Int -> a is TYPE r. I suppose the only way that could ever really bite you is if you were to run Core Lint on these types (which I certainly don't imagine happens today), but for the sake of consistency, it might be best just to update the kind of a in Int -> a anyways.

parseOption "not-home" = return (Just OptNotHome)
parseOption "show-extensions" = return (Just OptShowExtensions)
parseOption "print-runtime-reps" = return (Just OptPrintRuntimeRep)
parseOption "print-explicit-runtime-reps" = return (Just OptPrintRuntimeRep)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason for having two flags with the same effect? Why not just standardize on a single flag?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No particular reason. I want this flag to be called print-runtime-reps, but I anticipate some confusion with GHC's -fprint-explicit-runtime-reps (cf. Cabal's hyperlink-source option vs Haddock's hyperlinked-source option). Do you have an opinion one way or another?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My inclination would be to have -fprint-explicit-runtime-reps be the shared name of the flag across GHC and Haddock. I suppose I would be fine with picking -fprint-runtime-reps to be the name of the Haddock flag as well, but I definitely think we shouldn't come up with two different ways of referring to the same flag—that just seems like a recipe for confusion.

annot_ts = zipWith3 annotHsType is_poly_tvs ts ts'
is_poly_tvs = mkIsPolyTvs (tyConVisibleTyVars cls_tycon)
synifyClsIdSig = synifyIdSig DeleteTopLevelQuantification vs
synifyClsIdSig = synifyIdSig True DeleteTopLevelQuantification vs
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you hardcode PrintRuntimeReps to True here instead of consulting the flag?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. So this brings up a bigger question: should we thread through the RuntimeRep defaulting logic to everything involving Type in this module? Perhaps so, but that is going to be a fair bit of plumbing.

I think it is simpler to start with defaulting only top-level signatures, but I'm willing to be told otherwise.

Copy link
Member

@RyanGlScott RyanGlScott Sep 17, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If your goal is to avoid having any RuntimeRep quantification unless explicitly enabled, I think you'll eventually need to tackle class instances as well. After all, you can define levity polymorphic instances like so:

λ> class C a
λ> instance forall (r :: RuntimeRep) a (b :: TYPE r). C (a -> b)
λ> :i C
class C (a :: k)        -- Defined at <interactive>:2:1
instance [safe] forall a b. C (a -> b)
  -- Defined at <interactive>:3:10
λ> :set -fprint-explicit-runtime-reps 
λ> :i C
class C (a :: k)        -- Defined at <interactive>:2:1
instance [safe] forall (r :: RuntimeRep) a (b :: TYPE r).
                C (a -> b)
  -- Defined at <interactive>:3:10

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gah. Alright. Thanks for the motivating example. 😄

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Upon further inspection: I can't convince Haddock to ever print out runtime reps for instances. I'm inclined to leave this be for the moment. Plus this part of the wip/hi-haddock branch, so I'm trying to stay away from far-reaching changes.

Also patched up 'synifyTyCon' to do a better job on '(->)'.
Copy link
Member

@sjakobi sjakobi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few wibbles. :)

{-# OPTIONS_HADDOCK show-extensions #-}
Show all enabled LANGUAGE extensions
{-# OPTIONS_HADDOCK print-explicit-runtime-reps #-}
Don't default 'RuntimeRep' type variables
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sentence seems to be missing a print.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I missed that default is the verb here. I guess this could confuse other people too.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the description you used for the option parser:

Render runtime reps for this module (see the GHC @-fprint-explicit-runtime-reps@ flag)

-- | Whether or not to default 'RuntimeRep' variables to 'LiftedRep'. Check
-- out Note [Defaulting RuntimeRep variables] in IfaceType.hs for the
-- motivation.
type PrintRuntimeReps = Bool
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have a newtype or a custom type instead of the alias here?

Aliases tend to be refactored to the underlying types in my experience. Also, an explicit True or False doesn't say much about its purpose.

let renamer = docIdEnvRenamer (docs_id_env mod_iface_docs)

opts <- liftErrMsg $ mkDocOpts (docs_haddock_opts mod_iface_docs) flags mdl
let prr = OptPrintRuntimeRep `elem` opts
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather have a more meaningful variable name in this module.

@sjakobi sjakobi merged commit d7259c5 into haskell:wip/hi-haddock Sep 29, 2018
@sjakobi
Copy link
Member

sjakobi commented Sep 29, 2018

Thanks! :)

@harpocrates harpocrates deleted the default-runtime-rep branch October 16, 2018 19:59
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants