[GHC] #8177: Roles for type families
GHC
ghc-devs at haskell.org
Thu Sep 11 13:33:41 UTC 2014
#8177: Roles for type families
-------------------------------------+-------------------------------------
Reporter: simonpj | Owner: goldfire
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 7.6.3
Resolution: | Keywords:
Operating System: | Architecture: Unknown/Multiple
Unknown/Multiple | Difficulty: Unknown
Type of failure: | Blocked By:
None/Unknown | Related Tickets:
Test Case: |
Blocking: |
Differential Revisions: |
-------------------------------------+-------------------------------------
Comment (by dmcclean):
Yes, my apologies Simon.
This is actually going to be an interesting example, perhaps, because I
learned something about this since yesterday when I wrote that comment.
This example is slightly longer than I would like, I'm eliding a few
things but I'm not sure exactly which details (e.g. the data family being
associated) matter.
{{{
class KnownVariant (var :: Variant) where
-- | A dimensional value, either a 'Quantity' or a 'Unit', parameterized
by its 'Dimension' and representation.
data Dimensional var :: Dimension -> * -> *
-- elided: some functions to allow us to introduce and eliminate the
quantities or units
instance KnownVariant DQuantity where
newtype Dimensional DQuantity d v = Quantity' v
deriving (Eq, Ord, Enum)
-- elided: function implementations
instance KnownVariant (DUnit p) where
data Dimensional (DUnit p) d v = Unit' UnitName v
-- elided: function implementations
data Variant = DQuantity | DUnit Prefixability
type Quantity = Dimensional DQuantity
type Unit p = Dimensional (DUnit p)
}}}
So I set up all that machinery, and then I was curious whether we could
`coerce` in and out of the `Dimensional DQuantity d` newtype. So I thought
that the way to find out was by asking GHCi what the role of `Dimensional`
was. In concept it's `nominal phantom representational`, but it would be
extremely complicated for the compiler to see that because it would have
to examine all the (both the) instances and so forth, so I didn't know
what to expect.
{{{
Numeric.Units.Dimensional.DK> :i Dimensional
class KnownVariant (var :: Variant) where
type role Dimensional nominal nominal nominal
data family Dimensional (var :: Variant) ($a :: Dimension) $b
...
}}}
So I read that, and thought that it meant we were out of luck.
But, unexpectedly to me, but undoubtedly for a reason that is quite
obvious to someone, and this is the part I only discovered last night:
{{{
> let x = 3.7 :: Double
> x
3.7
> let y = (coerce x) :: Mass Double
> y
3.7 kg
> let x' = (coerce y) :: Double
> x'
3.7
}}}
Somehow it even seems to be OK when you abstract over the dimension with
RankNTypes, which isn't really a need but is just something I thought to
investigate to see if that was the difference between my expectation of
how this would work and how it in fact did work.
{{{
> let f = coerce :: (forall d.Double -> Quantity d Double)
> (f 3) :: Mass Double
3.0 kg
}}}
In conclusion, I now believe that I was too hasty yesterday, and that in
fact this ticket doesn't impact me at all.
My sincere apologies to everyone copied on this ticket. If someone
happened to have the time and knew the answer, it would be awesome if you
you could help me fix my understanding about whether this should or
shouldn't work and what the interplay with roles is, but otherwise I will
merrily go about my business. :)
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/8177#comment:20>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list