> 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




Reply via email to