> data Weirder a b = Weirdest a b
>
> class Weird c where
> f1 :: c -> c
> f2 :: Weirder a b -> c -> Weirder a b
> f3 :: Weirder a c -> Weirder c a
> f4 :: c -> c -> Bool
>
> instance Weird (d,e) where
> f1 (x,y) = (x,y)
> f2 w (x,y) = Weirdest x y
> f3 (Weirdest x y) = Weirdest y x
> f4 (x,y) z = True
>
> The complaint is:
>
> ERROR "x.hs" (line 11): Declared type too general
> *** Expression : f2
> *** Declared type : Weirder a b -> (c,d) -> Weirder a b
> *** Inferred type : Weirder a b -> (a,b) -> Weirder a b
>
> It is complaining that in the class, the type of the second
> parameter to function f2 has a simple type "(c,d)", which is unrelated
> to the type of the arguments to the constructor Weirdest, namely a and b.
That's exactly the complaint.
> In the instance, the type of the second argument to f2 must be the same
> types as the arguments to the constructor Weirdest. But this is exactly what
> I want, I want the function in the instance to be valid over a more specific
> type than in the class. This seems to have worked for f1, f3 and f4, but
> not for f2. What am I missing here? Is there a way to define this?
In f1, f3, f4, the way in which the instance is "more specific" is that a type
variable (c, in the class decl) is instantiated by a type. So for f1, the
class decl
said
f1 :: c -> c
and the instance decl instantiated c to (d,e), giving the type
f1 :: (d,e) -> (d,e)
And that is indeed the type of the f1 you give in the instance decl. Ditto
f3, f4.
But for f2, if we instantiate "c" we get
f2 :: Weirder a b -> (d,e) -> Wierder a b
You correctly say that you want a still more specific type. Without
understanding your application better I am nervous about recommending
this, but you *can* get what you say you want by using a multi-parameter class
class Weird a b c where
...
f2 :: Weirder a b -> c -> Wierder a b
...
and now use the instance
instance Weird d e (d,e) where
f2 w (x,y) = Weirdest x y
But multi-parameter type classes aren't a panacea. It may be that there's a
more direct
way to achieve what you really want.
Simon