[GHC] #11642: Heterogeneous type equality evidence ignored
GHC
ghc-devs at haskell.org
Tue Mar 15 21:48:00 UTC 2016
#11642: Heterogeneous type equality evidence ignored
-------------------------------------+-------------------------------------
Reporter: bgamari | Owner: goldfire
Type: bug | Status: closed
Priority: highest | Milestone: 8.0.1
Component: Compiler (Type | Version: 7.10.3
checker) |
Resolution: invalid | Keywords: TypeInType
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: |
-------------------------------------+-------------------------------------
Changes (by goldfire):
* status: new => closed
* resolution: => invalid
Comment:
A maze this is, indeed. But, happily(?), we humans were the ones lost, not
GHC, which is spot on.
The original code is
{{{#!hs
buildApp :: TypeRepX -> TypeRepX -> TypeRepX
buildApp (TypeRepX f) (TypeRepX x) =
case typeRepKind f of
TRFun arg _ ->
case eqTypeRep arg x of
Just HRefl ->
TypeRepX $ TypeApp f x
}}}
Let me augment with some kinds and such:
{{{#!hs
buildApp :: TypeRepX -> TypeRepX -> TypeRepX
buildApp (TypeRepX f) (TypeRepX x) =
-- f :: TypeRep kind_tf (tf :: kind_tf)
-- x :: TypeRep kind_tx (tx :: kind_tx)
case typeRepKind f of
TRFun arg _ ->
-- arg :: TypeRep kind_targ (targ :: kind_targ)
-- _ :: TypeRep kind_tres (tres :: kind_tres)
-- _ :: kind_tf ~ (targ -> tres)
-- _ :: kind_targ ~ *
-- _ :: kind_tres ~ *
case eqTypeRep arg x of
Just HRefl ->
-- _ :: kind_targ ~ kind_tx (but kind_targ ~ *)
-- _ :: targ ~ tx
TypeRepX $ TypeApp f x
-- NEED: exists k1 k2.
-- kind_tf ~ k1 -> k2
-- kind_tx ~ k1
}}}
At the end, we need to find `k1` and `k2` such that those two equalities
are provable from our givens. The choice of `k1` and `k2` is quite clear:
choose `k1 := targ` and `k2 := tres`. Now, we must prove `kind_tx ~ targ`.
But we can't! We know that `targ ~ tx`, not `targ ~ kind_tx`. Note that,
actually, `kind_tx` is really known to be `*`. So GHC helpfully reports
{{{
T11642.hs:47:30: error:
• Could not deduce: arg ~ *
from the context: k ~ (arg -> res)
bound by a pattern with pattern synonym:
TRFun :: forall fun arg res.
(fun ~ (arg -> res)) =>
TypeRep arg -> TypeRep res -> TypeRep fun,
in a case alternative
at T11642.hs:37:5-15
or from: (* ~ k1, arg ~ a1)
bound by a pattern with constructor:
HRefl :: forall k2 (a :: k2). a :~~: a,
in a case alternative
at T11642.hs:44:14-18
‘arg’ is a rigid type variable bound by
a pattern with pattern synonym:
TRFun :: forall fun arg res.
(fun ~ (arg -> res)) =>
TypeRep arg -> TypeRep res -> TypeRep fun,
in a case alternative
at T11642.hs:37:5
Expected type: TypeRep a
Actual type: TypeRep a
• In the first argument of ‘TypeApp’, namely ‘f’
In the second argument of ‘($)’, namely ‘TypeApp f x’
In the expression: TypeRepX $ TypeApp f x
• Relevant bindings include
arg :: TypeRep arg (bound at T11642.hs:37:11)
}}}
Which is absolutely correct.
Happily, fixing the code is easy:
{{{#!hs
-- ...
case eqTypeRep arg (typeRepKind x) of
-- ...
}}}
works like a charm.
I do believe some intermediate work (between when this was reported and
now) has improved this message. It's still not great, given that it took
me the better part of an hour to deduce all of the above. But I don't see
how we can do better without giving the user the trail of breadcrumbs that
GHC used to find its result. (I ''do'' think we should give this ability
to the user, somehow. It would be easy enough to implement -- just augment
`CtLoc` to keep track of previous constraints and how they were
transformed. The data is all there.)
I'm thus closing this as invalid. I'm also not adding a regression test,
because I'm not thrilled with the error message as it is, and there's no
other unusual behavior here.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/11642#comment:10>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list