Why distinct tyvars in instance declarations?

Hello, I'm a new Haskeller, and I'm running into a problem attempting to declare certain types as instances. I was attempting something that's effectively equivalent to:
class Foo a
instance Foo (Either b b)
but GHC complains:
Illegal instance declaration for `Foo (Either b b)' (The instance type must be of form (T a b c) where T is not a synonym, and a,b,c are distinct type variables) In the instance declaration for `Foo (Either b b)'
and so I looked in the report (http://www.haskell.org/onlinereport/decls.html#sect4.3.2) and found:
The general form of the corresponding instance declaration is:
instance cx' => C (T u1 ... uk) where { d }
where k>=0. The type (T u1 ... uk) must take the form of a type constructor T applied to simple type variables u1, ... uk; furthermore, T must not be a type synonym, and *the ui must all be distinct*. (emphasis mine)
My question is, why this restriction that the types must be distinct? In particular, I'd like to declare a very specific type (Either String String) as an instance. What techniques can I use to accomplish this? Josh Hoyt

Am Samstag, 25. Juni 2005 21:22 schrieb Josh Hoyt:
Hello,
I'm a new Haskeller, and I'm running into a problem attempting to declare certain types as instances. I was attempting something that's
effectively equivalent to:
class Foo a
instance Foo (Either b b)
but GHC complains:
Illegal instance declaration for `Foo (Either b b)' (The instance type must be of form (T a b c) where T is not a synonym, and a,b,c are distinct type variables) In the instance declaration for `Foo (Either b b)'
and so I looked in the report
(http://www.haskell.org/onlinereport/decls.html#sect4.3.2) and found:
The general form of the corresponding instance declaration is:
instance cx' => C (T u1 ... uk) where { d }
where k>=0. The type (T u1 ... uk) must take the form of a type constructor T applied to simple type variables u1, ... uk; furthermore, T must not be a type synonym, and *the ui must all be distinct*. (emphasis mine)
My question is, why this restriction that the types must be distinct?
In particular, I'd like to declare a very specific type (Either String String) as an instance. What techniques can I use to accomplish this?
Josh Hoyt
I don't know, why the tyvars must be distinct in Haskell 98, but if you use extensions (hugs -98; -fglasgow-exts for ghc(i)), you can declare instance Foo (Either b b) where ... or instance Foo (Either String String) where ... without problems. HTH, Daniel

On Sun, 26 Jun 2005, Daniel Fischer wrote:
Am Samstag, 25. Juni 2005 21:22 schrieb Josh Hoyt:
Hello,
I'm a new Haskeller, and I'm running into a problem attempting to declare certain types as instances. I was attempting something that's
effectively equivalent to:
class Foo a
instance Foo (Either b b)
My question is, why this restriction that the types must be distinct?
In particular, I'd like to declare a very specific type (Either String String) as an instance. What techniques can I use to accomplish this?
Josh Hoyt
I don't know, why the tyvars must be distinct in Haskell 98,
This is certainly to prevent from overlapping instances. An implementation for general (Either a b) could also be invoked when (Either String String) is requested. If it is really necessary to make the Either type an instance of something better use a data or a newtype definition. newtype EitherString = EitherString (Either String String) and declare an instance for EitherString.

On 6/26/05, Henning Thielemann
On Sun, 26 Jun 2005, Daniel Fischer wrote:
[...] I don't know, why the tyvars must be distinct in Haskell 98,
This is certainly to prevent from overlapping instances. An implementation for general (Either a b) could also be invoked when (Either String String) is requested.
If it is really necessary to make the Either type an instance of something better use a data or a newtype definition.
newtype EitherString = EitherString (Either String String)
and declare an instance for EitherString.
I see why there is ambiguity between (Either a b) and (Either b b). In fact, it seems rather obvious now. Thanks for your help. Just to make sure I understand, and hopefully instructive for others who run into the same difficulty: class Foo a where frob :: a -> String {- Illegal: instance Foo (Either String String) where frob (Right x) = x frob (Left y) = y -} -- Instead: -- Option a: -- Generic implementation in terms of other classes instance (Show a, Show b) => Foo (Either a b) where frob (Right x) = show x frob (Left y) = show y -- Option b: -- Let the type system know that this is a specific case by defining a type newtype EitherString = EitherString (Either String String) instance Foo EitherString where frob (EitherString (Right x)) = x frob (EitherString (Left y)) = y
participants (3)
-
Daniel Fischer
-
Henning Thielemann
-
Josh Hoyt