[GHC] #9918: GHC chooses an instance between two overlapping, but cannot resolve a clause within the similar closed type family
GHC
ghc-devs at haskell.org
Tue Jan 13 09:34:04 UTC 2015
#9918: GHC chooses an instance between two overlapping, but cannot resolve a
clause within the similar closed type family
-------------------------------------+-------------------------------------
Reporter: qnikst | Owner:
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 7.8.3
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture:
Type of failure: None/Unknown | Unknown/Multiple
Blocked By: | Test Case:
Related Tickets: | Blocking:
| Differential Revisions:
-------------------------------------+-------------------------------------
Comment (by oleg):
I too have tried to induce unsoundness with overlapping instances and
concluded it is unlikely -- although there is plenty of strange and
incoherent behavior one can observe. The straightforward attempt to
pack an existential in one type class environment and unpack it in
another module (where a more specialized instance is introduced) does
not work because the existential is packed with the corresponding
dictionary. When it is unpacked, the packed dictionary is used --
regardless how many new instances become available.
Without type families, a type variable always stood for some ground
type, at least potentially. When we assert a constraint C a on the
type variable a, that constraint will not be dropped or discarded. It
will be explicitly passed around, until it is resolved (or cannot be
resolved -- in which case an error is reported). That is why it is
safe to do instance selection for unground types: if we have
{{{
class C a where foo :: a -> Int
instance C [a] where foo = length
test3 x = foo [x]
}}}
the inferred type for test3 :: t -> Int has no constraints. We
resolved C [t] for the unground type t. If t had other constraints,
they will be preserved.
With type functions, we are no longer sure what the type variable
represents. It can be a non-reduced type-function application. So a
type variable now stands not for a value (ground type) but for an
expression. And that could be a problem. For example:
{{{
type family TT a
-- no instances
newtype D a = D{unD:: [TT a]}
test4 (x::a) = foo (unD (undefined:: D a))
test5 (x::a) = foo (unD (D []:: D a))
}}}
The code type-checks and test5 () even runs, returning 0. So,
although T a has no instances, we have successfully ignored that fact.
That trick would not have worked with only type classes; if we add a
constraint we can't cast it away, and the type checker will demand
sooner or later the constraint be satisfied.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/9918#comment:19>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list