Having this:
data Rectangle = Rectangle Height Width
data Circle = Circle Radius
class Shape a where
area :: a -> Float
perimeter :: a -> Float
instance Shape Rectangle where
area (Rectangle h w) = h * w
perimeter (Rectangle h w) = 2*h+w*2
instance Shape Circle where
area (Circle r) = pi * r**2
perimeter (Circle r) = 2*pi*r
volumenPrism base height = (area base) * height
surfacePrism shape h = (area shape) * 2 + perimeter shape * h
Why cant I write this? a
is a type so why doesn't this work?
instance (Shape a) => Eq a where
x==y = area x == area y
Obviously doing like this:
instance Eq Circle where
x==y = area x == area y
first for Circle and then for Rectangle works..but it seems not the right way.
What is it I don't get in all this?
Ty
The fundamental problem is that the type class instance resolution machinery doesn't backtrack. So if you write instance Shape a => Eq a
, then whenever the compiler wants to find an Eq
instance, the compiler will try to use this instance and for most types it won't work out because they aren't instances of Shape
.
If you still really want to do this, you can add
{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
at the top of your source file.
You can also work round some of the problems described above by also adding OverlappingInstances
to the set of LANGUAGE pragmas, but you will still have a global instance for Eq
that will cause significant confusion elsewhere in your program.
It's much better to just enumerate the instances you really need, even if it seems ugly. You can keep the boilerplate to a minimum with a helper function, e.g.
x `areaEq` y = area x == area y
and then
instance Eq Circle where
(==) = areaEq
etc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With