[GHC] #8503: New GeneralizedNewtypeDeriving check still isn't permissive enough
GHC
ghc-devs at haskell.org
Tue Nov 5 21:17:22 UTC 2013
#8503: New GeneralizedNewtypeDeriving check still isn't permissive enough
-------------------------------------+------------------------------------
Reporter: goldfire | Owner: goldfire
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 7.7
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture: Unknown/Multiple
Type of failure: None/Unknown | Difficulty: Unknown
Test Case: | Blocked By:
Blocking: | Related Tickets:
-------------------------------------+------------------------------------
Comment (by goldfire):
Hold the phone! There is an easier solution to the original problem!
In my first comment, I wanted a coercion `co :: forall (a :: *). Maybe
(Maybe a) ~R NTMaybe (NTMaybe a)`, and then I proposed a possible value of
that type that was ill-roled. But, here is a well-roled value:
{{{
co = co1 ; co2
co1 :: forall (a :: *). Maybe (Maybe a) ~R Maybe (NT a)
co1 = forall (a :: *). Maybe (sym NTCo <a>_N)
co2 :: forall (a :: *). Maybe (NT a) ~R NT (NT a)
co2 = forall (a :: *). sym NTCo <NT a>_N
}}}
If we convert the pieces one at a time and then use transitivity, we're
all OK. I remember battling against this problem over the summer.
So, now we have a new question: how to get GHC to find this solution?
Luckily, we happen to have a solver lying around that does just that: the
`Coercible` mechanism. I imagine we could get the GND code to just call
the `Coercible` code for each method. In fact, I considered this approach
when improving the GND mechanism a few weeks ago, but thought it was
overkill.
My guess is that this would Just Work, when implemented. It might simplify
the code a bit, too, but be somewhat less efficient (at compile time) at
doing GND. I think this is reasonable.
Taking the idea a bit further, what if the `Coercible` mechanism can't
derive a coercion for a particular method? It would have to produce
unsolved `Coercible` constraints... which we could just add to the
constraints on the GND instance! This would allow more GND's to work than
we had hoped for, such as this example:
{{{
type family F a
class C a where
meth :: a -> F a
type instance F Int = Bool
class C Int where
meth = (> 0)
type instance F Age = Bool
newtype Age = MkAge Int
deriving C -- just works, no extra constraints because F Age = F
Int
type instance F [a] = a
class C [a] where
meth = head
type instance F (List a) = Int
newtype List a = MkL [a]
deriving C -- this would create an instance with head "instance
(Coercible a Int) => C (List a) where ..."
}}}
This all seems quite reasonable behavior, though we would want to make
sure we don't produce constraints like `Coercible Int Bool`.
Thoughts? Is this a good plan? We could always, as a first pass, implement
GND in terms of `Coercible` and fail if there are any unsolved
constraints, working for `C Age` above but not `C (List a)`.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/8503#comment:9>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list