[Haskell] Instance declaration of classes with method type constraints

robert dockins robdockins at fastmail.fm
Wed Jun 29 16:22:05 EDT 2005


> Hi,
> 
> How do you instantiate from classes with method type constraints, such as this 
> one:
> 
> class C a where
>    m :: (Num b) => a -> b

This type declaration for 'm' probably doesn't mean what you think it 
does.  I think what you want is "m takes an item of type 'a' and returns 
an item of a particular type in the Num class, but I'm not going to tell 
you which one", but what this declaration really means "m takes an item 
of type 'a' and will return an item of any type you wish, so long as it 
is in the Num class".

In this context 'a' and 'b' are very different kinds of type variables: 
'a' is fixed, but 'b' is universally quantified.

> I have been trying for some time now but everything I have tried fails.
> 
> In particular, what I want to do is something like this:
> 
> class Rect a where
> 	width  :: (Num b) => a -> b
> 	height :: (Num b) => a -> b
> 
> data Num a => PRect a = PRect (a, a) (a, a) deriving (Eq, Show)
> data IRect = IRect (Int, Int) (Int, Int) deriving (Eq, Show)
> 
> instance Rect IRect where
> 	width  ( IRect (x1, _ ) (x2, _ ) ) = abs(x2 - x1)
> 	height ( IRect ( _, y1) ( _, y2) ) = abs(y2 - y1)
> 
> In this case, efforts to intantiate IRect from Rect fails with error messages 
> like: (using GHCI)
> -----8<-----
> classtest2.hs:29:
>     Cannot unify the type-signature variable `b' with the type `Int'
>         Expected type: b
>         Inferred type: Int
>     In the expression: x2 - x1
>     In the first argument of `abs', namely `(x2 - x1)'
> -----8<-----

The easy fix is to add a call to 'fromIntegral', eg

    .... = fromIntegral (abs (x2 - x1))

but again, it probably doesn't mean what you want it to mean.

Probably what you want is something like this (but requires GHC extensions):

{-# OPTIONS -fglasgow-exts #-}
class Num b => Rect a b | a -> b where
     width :: a -> b
     height :: a -> b

instance Rect IRect Int where
    width  ( IRect (x1, _ ) (x2, _ ) ) = abs(x2 - x1)
    height ( IRect ( _, y1) ( _, y2) ) = abs(y2 - y1)





More information about the Haskell mailing list