[GHC] #12466: Typechecker regression: Inaccessible code in a type expected by the context
GHC
ghc-devs at haskell.org
Thu Aug 25 16:08:25 UTC 2016
#12466: Typechecker regression: Inaccessible code in a type expected by the context
-------------------------------------+-------------------------------------
Reporter: RyanGlScott | Owner:
Type: bug | Status: new
Priority: highest | Milestone: 8.0.2
Component: Compiler (Type | Version: 8.1
checker) |
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture:
Type of failure: GHC rejects | Unknown/Multiple
valid program | Test Case:
Blocked By: | Blocking:
Related Tickets: | Differential Rev(s):
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by ekmett):
I think there is morally a difference between
{{{#!hs
class Foo a where
foo :: (a ~ Int => a) -> a -> a
}}}
and your example which is more like
{{{#!hs
class Foo a where
foo :: (a ~ Int) => a -> a -> a
}}}
in terms of if we should reject things once we know `a ~ Char`, and that
hence `a ~ Int` can never happen.
In the former you're given two arguments, one of which requires you to
provide something impossible to use, and so simply cant be used, while in
the latter you're required to implement a contradiction when you go to
write `instance Foo Char`.
Notice the polarity of the equality constraint. In the former it is in
positive position. In the latter it is in negative position as usual.
Finding a contradiction in negative position fits with Richard's intuition
about if we should complain, but in positive position it simply means that
argument is inaccessible, which is perfectly okay.
Someone might pass it in in a more polymorphic setting where they don't
know if the constraint could be satisfied or not, until the instance for
Foo is selected, which is what is happening here.
Today I usually hack around the latter by passing an explicit Dict for the
constraint, so that I have the option to bring it into scope or not, and
can carefully avoid GHC prematurely detonating upon discovering the
contradiction
{{{#!hs
class Foo a where
foo :: Dict (a ~ Int) -> a -> a -> a
}}}
but until now I haven't had to hack around it for the former -- and the
explicit Dict-based solutions are much clunkier to both write, and for
users to use in practice. (We used to use this approach to implement ex
falso quodlibet in the `constraints` package, but now we just use `Any`
directly as an uninhabitable initial `Constraint`.)
> Currently
{{{#!hs
foo :: (Char ~ Int => Int) -> a -> a
foo _ a2 = a2
}}}
> gives a similar message. Is that reasonable? The argument to foo can't
be called.
I'd personally think that that should be allowed, as silly as it looks in
this very concrete case. `foo` itself doesn't care about the argument at
all. The burden of complaining about the impossibility of what we can see
locally would be `Int ~ Char` should fall on type checking the argument
passed to `foo` at the call site, not to `foo`, and at that call site it
may or may not be impossible as it may not know the `Int` part of the
equation there.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/12466#comment:23>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list