error-messages
error-messages copied to clipboard
Scoped type variables not suggested
Consider the following file:
module ErrMsg where
f :: a -> a
f x = y
where
y :: a
y = x
When loaded up in GHCi we get the following error message:
ErrMsg.hs:7:9: error:
• Couldn't match expected type ‘a1’ with actual type ‘a’
‘a1’ is a rigid type variable bound by
the type signature for:
y :: forall a1. a1
at ErrMsg.hs:6:5-10
‘a’ is a rigid type variable bound by
the type signature for:
f :: forall a. a -> a
at ErrMsg.hs:3:1-11
• In the expression: x
In an equation for ‘y’: y = x
In an equation for ‘f’:
f x
= y
where
y :: a
y = x
• Relevant bindings include
y :: a1 (bound at ErrMsg.hs:7:5)
x :: a (bound at ErrMsg.hs:4:3)
f :: a -> a (bound at ErrMsg.hs:4:1)
|
7 | y = x
|
The fact that ScopedTypeVariables is never even mentioned is particularly egregious, in my opinion. Also, note that the same error message is produced with ScopedTypeVariables enabled, and doesn't mention using an explicit forall.
Suggested error message
When ScopedTypeVariables is off:
• Couldn't match expected type ‘a1’ with actual type ‘a’
The type variable ‘a’ is not in scope in the type signature
for ‘y’, therefore it gets renamed to ‘a1’ and is not the same
as ‘a’
Consider enabling ScopedTypeVariables and including an explicit
forall in the type signature for ‘f’ in order to bring ‘a’ into scope
• Relevant type variables include
‘a1’ (bound at ErrMsg.hs:6:5-10, in the signature for ‘y’)
‘a’ (bound at ErrMsg.hs:3:1-11, in the signature for ‘f’)
• Relevant bindings include
y :: a1 (bound at ErrMsg.hs:7:5)
x :: a (bound at ErrMsg.hs:4:3)
f :: a -> a (bound at ErrMsg.hs:4:1)
|
7 | y = x
| ^
When ScopedTypeVariables is on simply replace this line:
Consider enabling ScopedTypeVariables and including an explicit
forall in the type signature for ‘f’ in order to bring ‘a’ into scope
With this:
Consider including an explicit forall in the type signature for ‘f’
in order to bring ‘a’ into scope
This sort of error would also benefit greatly from having a further explanation linked. I've seen discussions of giving errors unique ids and having a collection of explanations that can be referenced. This seems like a good application for that.
This specific issue is what I remember being confused by the most, as a beginner. It wasn't immediately clear to me that, the a I bound inside the function scope, wasn't the same as the a bound within the function type itself.
Yes, I think this should be doable. Permit me to offer small tweaks to the new messages:
Without -XScopedTypeVariables
• Couldn't match expected type ‘a1’ with actual type ‘a’
The type variable ‘a’ is not in scope in the type signature
for ‘y’; it therefore is considered a fresh variable, not equal
to any other. To bring ‘a’ into scope:
1. Enable the ScopedTypeVariables extension
2. Rewrite 'f :: a -> a' to 'f :: forall a. a -> a'.
• In the expression: x
In an equation for ‘y’: y = x
In an equation for ‘f’:
f x
= y
where
y :: a
y = x
• Relevant type variables include
‘a1’ (bound at ErrMsg.hs:6:5-10, in the signature for ‘y’)
‘a’ (bound at ErrMsg.hs:3:1-11, in the signature for ‘f’)
• Relevant bindings include
y :: a1 (bound at ErrMsg.hs:7:5)
x :: a (bound at ErrMsg.hs:4:3)
f :: a -> a (bound at ErrMsg.hs:4:1)
|
7 | y = x
|
With -XScopedTypeVariables:
• Couldn't match expected type ‘a1’ with actual type ‘a’
The type variable ‘a’ is not in scope in the type signature
for ‘y’; it therefore is considered a fresh variable, not equal
to any other. To bring ‘a’ into scope:
Rewrite 'f :: a -> a' to 'f :: forall a. a -> a'.
• In the expression: x
In an equation for ‘y’: y = x
In an equation for ‘f’:
f x
= y
where
y :: a
y = x
• Relevant type variables include
‘a1’ (bound at ErrMsg.hs:6:5-10, in the signature for ‘y’)
‘a’ (bound at ErrMsg.hs:3:1-11, in the signature for ‘f’)
• Relevant bindings include
y :: a1 (bound at ErrMsg.hs:7:5)
x :: a (bound at ErrMsg.hs:4:3)
f :: a -> a (bound at ErrMsg.hs:4:1)
|
7 | y = x
|
I have kept the context (the "In the ..." lines) and rephrased the suggestion somewhat. If we're happy with this, would someone make a GHC ticket?
https://gitlab.haskell.org/ghc/ghc/-/issues/20308
Assuming (knock on wood) https://github.com/ghc-proposals/ghc-proposals/pull/448 gets accepted, we have some new stuff to consider here.
module ErrMsg where
f :: forall a. a -> a
f x = y
where
y :: a
y = x
With -XNoImplicitForAll, the second a is out of scope, and we get no type error. Nice and simple!
Without, I think the -XTypeAbstractions solutions are better:
module ErrMsg where
f :: forall a. a -> a
f @a x = y
where
y :: a
y = x
or
module ErrMsg where
f :: forall a. a -> a
f @(..) x = y
where
y :: a
y = x