[GHC] #8503: New GeneralizedNewtypeDeriving check still isn't permissive enough
GHC
ghc-devs at haskell.org
Thu Nov 14 03:37:35 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):
Yuck.
I'm leery of creating a way for the type-checker to loop without turning
on `UndecidableInstances`. And, with the `R2` example that Simon gives,
the newtype and the relevant type family instance might be in different
modules, so detecting even so simple an infinite regress may be
problematic. (And, note that the pieces on their own are innocent-
looking.)
I've also just looked at `Note [Recursive newtypes]` in !TcDeriv. This
note explains why GND ''works'' for recursive newtypes. I repeat it here:
{{{
Note [Recursive newtypes]
~~~~~~~~~~~~~~~~~~~~~~~~~
Newtype deriving works fine, even if the newtype is recursive.
e.g. newtype S1 = S1 [T1 ()]
newtype T1 a = T1 (StateT S1 IO a ) deriving( Monad )
Remember, too, that type families are curretly (conservatively) given
a recursive flag, so this also allows newtype deriving to work
for type famillies.
We used to exclude recursive types, because we had a rather simple
minded way of generating the instance decl:
newtype A = MkA [A]
instance Eq [A] => Eq A -- Makes typechecker loop!
But now we require a simple context, so it's ok.
}}}
I'm confused by the last line. In the code above the note, a context is
generated that includes, for this example, `Eq [A]`! Where does the loop
get broken?
Regardless, here's a possible solution: if `Coercible` over recursive
newtypes is sound but otherwise in danger of causing a loop, we could just
require `UndecidableInstances` to get the `Coercible` mechanism to go down
this road. In this scenario, my example (with `RecNT`) would fail to use
GND without `UndecidableInstances` but should succeed with it. We can even
give a helpful error message in this scenario.
Or, perhaps even better: could the `Coercible` mechanism use
`TyCon.checkRecTc`? That function seems to be designed for exactly this
scenario, which is where we need to do newtype expansion but don't want to
fall into a black hole. That might complicate the `Coercible` code, but I
think it would be a step in the right direction. We could still allow
users to specify `UndecidableInstances` to bypass even this check... but
my guess is that `checkRecTc` would work exactly in the correct cases,
meaning that bypassing the check is sure to cause the type-checker to
loop. Other, more informed opinions are very welcome here.
Lastly, is there a solid reason to require that the recursiveness of a
type in a hs-boot file and the recursiveness of the real type are the
same? It looks to me that it would be sound to assume types in hs-boot
files are recursive, but then not to inherit this trait when processing
the real thing. That would fix the problem with compiling Module.lhs, and
it would save some embarrassment if we were to suggest
`UndecidableInstances` to compile a very ordinary-looking newtype!
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/8503#comment:13>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list