[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