[GHC] #8177: Roles for type families
GHC
ghc-devs at haskell.org
Sun Jun 25 16:22:34 UTC 2017
#8177: Roles for type families
-------------------------------------+-------------------------------------
Reporter: simonpj | Owner: goldfire
Type: bug | Status: new
Priority: normal | Milestone: ⊥
Component: Compiler | Version: 7.6.3
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): Phab:D3662
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by goldfire):
Replying to [comment:39 RyanGlScott]:
> Hoo boy, I was afraid you were going to demand a proof. I certainly
don't have one at the moment.
"Demand"? No. But it would be nice if the design could at least update the
various relevant judgments in the "Safe coercions" paper (use the JFP
version). It shouldn't be terribly much work, and it's likely that the
process of doing so will reveal any glaring problems. And once you have
the updated judgments, it's also not terribly hard to follow along the JFP
proof and see what lemmas have to be updated.
I'm always daunted by having to revisit the type safety proof. But every
time I go through the process, my brain feels nice, limber, and at peace.
It's all very much like a good yoga session: it's hard to find the time to
do it, it involves painful contortions, and yet you feel quite good at the
end.
> Ah, I think there's a bit of confusion regarding the extent of this
design. To be clear, I am not proposing that we give users the power to
specify roles the type variables in each //equation//, only the type
variables of the parent type family itself.
Note that instance-specific roles apply only to ''data'' families, not
''type'' families.
> This is because:
>
> 1. As your example hints at, we'd need to invent a new syntax for role
annotations that match on particular types, and I don't feel anywhere near
motivated enough to implement that.
And neither was I, as you'll see in my comment:5.
> 2. The current implementation of role inference does not lend itself
well to this design. GHC assigns roles by using a map from `TyCon` names
to roles, but type family equations have neither `TyCon`s nor any kind of
unique identifier from which we could look up its roles after inference.
This isn't as bad as you say. Data family instances ''do'' have a `TyCon`.
See the `DataFamilyInst` constructor of `FamInstEnv.FamFlavor`.
> 3. This kind of power isn't necessary for the kind of stuff I'd want to
do anyways. All I really care about is that the second parameter is
designated as `representational`. I don't really want the ability to
`coerce` between `DF (Maybe Age) Int` and `DF (Maybe Age) Int`.
So perhaps you want just roles for ''type'' families for now, not ''data''
families.
>
> So in your above example:
>
> {{{#!hs
> data family DF a b
> type role DF nominal representational
> data instance DF [c] b = MkDFList c b
> data instance DF (Maybe d) b = MkDFMaybe d b
> }}}
>
> I would propose that the tyvars in any type pattern which saturates `a`
should inherit the role of `a`, so `c` and `d` would get role `nominal` in
their respective equations. It's not as permissive as it //could// be, but
for reasons that I explained above (and I'll make a note of this in the
wiki).
But any time a pattern introduces a new tyvar (that's not just a renaming
of the tycon tyvar), then the "parent" tyvar's role is always nominal
(because you're doing pattern matching). As you note, this is not as
permissive as possible. But, I would argue that if you were as permissive
as possible, then you'd have no way of making a fully-abstract data family
instance. So your design is self-consistent.
>
> > I'm a bit worried about problems with what happens if a type
constructor that appears as part of a type pattern for an instance is
actually a newtype with a role annotation -- could we be breaking
soundness with this? Need to think harder.
>
> I don't understand this point.
I was worried about something like this:
{{{#!hs
newtype Inty a = MkInty Int
type role Inty representational -- just because I can
data family F a
type role F nominal
data instance F (Inty a) = MkF a
type role F (Inty nominal)
}}}
Is this a good idea? I don't know. Keep in mind that data families are
injective.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/8177#comment:40>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list