Reputation: 2800
I'm trying to define a type class Plotable
that provides a function plotable
to return a tuple representing co-ordinates in a chart (x,y)
, it the type of x
and y
does not have to be specific (ie Double
), I think they can be any number type (they're being handed over to Chart).
I want plotable
to be able to deal with Num a => Complex a
and Num a => (a, a)
, so I wrote:
class Plotable a where
plotable :: Num b => a -> (b, b)
instance Num a => Plotable (a, a) where
plotable = id
instance Num a => Plotable (Complex a) where
plotable c = (realPart c, imagPart c)
Which makes sense to me, however I'm getting the error:
Couldn't match type ‘a’ with ‘b’
‘a’ is a rigid type variable bound by
the instance declaration
at /Users/dan.brooks/Code/haskell/coding-the-matrix/src/TheField/Plot.hs:12:10-33
‘b’ is a rigid type variable bound by
the type signature for:
plotable :: forall b. Num b => (a, a) -> (b, b)
at /Users/dan.brooks/Code/haskell/coding-the-matrix/src/TheField/Plot.hs:13:3-10
Expected type: (a, a) -> (b, b)
Actual type: (b, b) -> (b, b)
But surely if a
is constrained to Num
, and b
is constrained to Num
, passing through the same value should work in this case? Is this simply a limitation of the compilier? or am I misusing typeclasses and type constraints?
Upvotes: 0
Views: 72
Reputation: 116139
plotable :: Num b => a -> (b, b)
means that any of these must type check
plotable :: a -> (Int, Int)
plotable :: a -> (Integer, Integer)
plotable :: a -> (Double, Double)
...
In other words, that polymorphic type promises to the user that plotable
can use whichever numeric type b
the user can choose.
id :: a -> a
does not let the user choose b
, so it is not general enough.
Upvotes: 1