[GHC] #9223: Type equality makes type variable untouchable
GHC
ghc-devs at haskell.org
Mon Jun 23 07:53:54 UTC 2014
#9223: Type equality makes type variable untouchable
--------------------------------------------+------------------------------
Reporter: Feuerbach | Owner:
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler (Type checker) | Version: 7.8.2
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture:
Type of failure: None/Unknown | Unknown/Multiple
Test Case: | Difficulty: Unknown
Blocking: | Blocked By:
| Related Tickets:
--------------------------------------------+------------------------------
Comment (by simonpj):
GHC is being schizophrenic about an interesting design choice here. The
issue is this.
When typechecking `x2`'s RHS, we assume that the RHS has type `alpha`, for
some fresh unification variable `alpha`, and generate constraints from the
RHS, giving the constraint:
{{{
forall m. (Monad m, TF m ~ ()) -- Comes from run2's type
=> (m alpha ~ m (), -- Matching result of (return ())
with expected type (m alpha)
Monad m) -- Call of return
}}}
That leads to the constraint `(alpha ~ ())`, but underneath an implication
constraint that has an equality (like a GADT) in it. So !OutsideIn
refrains from unifying `alpha`.
Then GHC tries to infer a type for `x2` anyway, getting (essentially)
{{{
x2 :: forall a. (a ~ ()) => a
}}}
where we have decided to quantify over `alpha` to `a`. Finally we end up
reporting the insoluble constraint `(a ~ alpha)`.
So the question is: what error message would you like to see? This
"untouchable" stuff is a bit disconcerting, so we could say this:
{{{
Couldn't match expected type ‘a’ with actual type ‘()’
‘a’ is a rigid type variable bound by
the inferred type of x2 :: forall a. a at untouchable.hs:15:1
Relevant bindings include x2 :: a (bound at untouchable.hs:15:1)
In the first argument of ‘return’, namely ‘()’
In the first argument of ‘run2’, namely ‘(return ())’
}}}
Here you get to see the inferred type of `x2`. (Side note: actually GHC
currently prints `the inferred type of x2 :: a`, suppressing the `forall`,
but in this context I suspect we should print the `forall` regardless of
`-fprint-explicit-foralls`. I'll make that change anyway unless anyone
yells.)
A merit of this error message is that if you, the programmer, give `x2`
that type signature `x2 :: forall a. a`, then indeed that is very much the
message that you'll get. But I suppose it leaves open the question of
'''why''' GHC inferred that type for `x2`.
Alternatively we could give you
{{{
Couldn't match expected type ‘a’ with actual type ‘()’
‘a’ is untouchable
inside the constraints (Monad m, TF m ~ ())
bound by a type expected by the context:
(Monad m, TF m ~ ()) => m a
at untouchable.hs:15:6-21
Relevant bindings include x2 :: a (bound at untouchable.hs:15:1)
In the first argument of ‘return’, namely ‘()’
In the first argument of ‘run2’, namely ‘(return ())’
}}}
which perhaps exposes a bit more of the mechanism of !OutsideIn, and has
the merit of displayin the constraint(s) that make it untouchable.
Which would you prefer? Currently GHC displays both, which I agree is
confusing.
Simon
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/9223#comment:2>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list