[GHC] #15827: Explicit foralls in type family equations are pretty-printed inconsistently (and strangely, at times)
GHC
ghc-devs at haskell.org
Mon Oct 29 13:11:18 UTC 2018
#15827: Explicit foralls in type family equations are pretty-printed inconsistently
(and strangely, at times)
-------------------------------------+-------------------------------------
Reporter: RyanGlScott | Owner: (none)
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 8.7
Resolution: | Keywords: TypeFamilies
Operating System: Unknown/Multiple | Architecture:
| Unknown/Multiple
Type of failure: None/Unknown | Test Case:
Blocked By: | Blocking:
Related Tickets: | Differential Rev(s):
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by RyanGlScott):
Hm, it appears that fixing this may not be as straightforward as I would
have hoped. The main issue that I encountered is that `:info` displays
type family equations by first converting them to their interface file
equivalents and then pretty-printing them. Take a look at
[http://git.haskell.org/ghc.git/blob/4427315a65b25db22e1754d41b43dd4b782b022f:/compiler/iface/IfaceSyn.hs#l215
IfaceAxBranch] (which is the interface file incarnation of a type family
equation), for instance:
{{{#!hs
data IfaceAxBranch = IfaceAxBranch { ifaxbTyVars :: [IfaceTvBndr]
, ifaxbCoVars :: [IfaceIdBndr]
, ... }
}}}
Notice that this stores type variable information (`ifaxbTyVars`) as
`IfaceTvBndr`s instead of `IfaceTyConBinder`s. This is an important
distinction because essentially all of the machinery within `IfaceType`
that pretty-prints explicit `forall`s works over `IfaceTyConBinder`s, not
`IfaceTvBndr`s. (This makes some amount of sense since an
`IfaceTyConBinder` stores visibility information but an `IfaceTvBinder`
does not.)
I suppose that we could just convert the `ifaxbTyVars` to
`IfaceTyConBinder`s (defaulting each variable's visibility to specified)
before pretty-printing. But there's another challenge: how should we print
the `ifaxbCoVars`? The
[http://git.haskell.org/ghc.git/blob/4427315a65b25db22e1754d41b43dd4b782b022f:/compiler/iface/IfaceSyn.hs#l560
existing code] for pretty-printing `IfaceAxBranch`es actually does take
`ifaxbCoVars` into account at the moment:
{{{#!hs
pprAxBranch pp_tc (IfaceAxBranch { ifaxbTyVars = tvs
, ifaxbCoVars = cvs
, ifaxbLHS = pat_tys
, ifaxbRHS = rhs
, ifaxbIncomps = incomps })
= hang ppr_binders 2 (hang pp_lhs 2 (equals <+> ppr rhs))
$+$
nest 2 maybe_incomps
where
ppr_binders = sdocWithDynFlags $ \dflags ->
ppWhen (gopt Opt_PrintExplicitForalls dflags)
ppr_binders'
ppr_binders'
| null tvs && null cvs = empty
| null cvs
= brackets (pprWithCommas (pprIfaceTvBndr True) tvs)
| otherwise
= brackets (pprWithCommas (pprIfaceTvBndr True) tvs <> semi <+>
pprWithCommas pprIfaceIdBndr cvs)
}}}
I'm not sure what this code should become if we start using the `forall`
keyword instead. To make things even more confusing, the
[http://git.haskell.org/ghc.git/blob/4427315a65b25db22e1754d41b43dd4b782b022f:/compiler/types/CoAxiom.hs#l219
comments] for `CoAxBranch`:
{{{#!hs
data CoAxBranch
= CoAxBranch
{ ...
, cab_tvs :: [TyVar] -- Bound type variables; not
necessarily fresh
-- See Note [CoAxBranch type
variables]
-- May be eta-reduded; see FamInstEnv
-- Note [Eta reduction for data
families]
, cab_cvs :: [CoVar] -- Bound coercion variables
-- Always empty, for now.
-- See Note [Constraints in patterns]
-- in TcTyClsDecls
, ...
}
}}}
Suggest that the bound coercion variables in a coaxiom branch are always
empty in practice! So is it even worth fretting over them? Perhaps an
expert in this area could answer this question, but I'm far from that
expert.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/15827#comment:1>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list