The Haskell wiki on ScopedTypeVariables does not describe how the scope of a type variable is handled between a type class and its instance.
The following compiles
{-# LANGUAGE ScopedTypeVariables #-}
class A a where
f :: forall b. a -> b -> (a,b)
instance A Int where
f a b = (idb a, ida b)
where idb :: b -> b
idb = id
ida :: a -> a
ida = id
while the following does not (as expected: Couldn't match expected type ‘a’ with actual type ‘b’)
g :: forall a b. a -> b -> (a,b)
g a b = (idb a, b)
where idb :: b -> b
idb = id
Since the wiki is silent, how was ScopedTypeVariables supposed to work with type classes? Is this a bug, a misfeature, or by design? The wiki mentions some work-arounds that are Haskell98 and they seem to be compatible with using type classes (and thus superior).
EDIT:
As mentioned in a comment, InstanceSigs makes it possible to re-introduce the signature from the class and thus bring the type variables into scope. But this seems very awkward compared to the Haskell98 alternative:
data D
instance A D where
f a b = (idb a, b)
where idb x = asTypeOf b x -- gives the correct error message
{-# LANGUAGE InstanceSigs #-}
data E
instance A E where
-- Complicated way to bring the class signature into scope..?
f :: forall b. E -> b -> (E, b)
f a b = (idb a, b)
where idb :: b -> b
idb = id
Doesn't it make more sense that the scope from the class declaration is re-used in the instance declaration to make ScopedTypeVariables work nicely with type classes?
InstanceSigsand explicitly givef :: forall b. Int -> b -> (Int, b)in the instance, the code fails to compile. - David YoungInstanceSigsI would have to repeat the signature. However, if I wroteidb x = asTypeOf b xwhich is the Haskell98 "workaround", I think I would get the compile error. - user239558forallto explicitly bring them into scope? - user239558