Reputation: 23068
I'm trying to get the type Shape
to re-use the types Circle
and Rectangle
data Point = Point {
x :: Float,
y :: Float
} deriving (Show)
data Circle = Circle {
c :: Point,
r :: Float
} deriving (Show)
data Rectangle = Rectangle {
p1 :: Point,
p2 :: Point
} deriving (Show)
-- the following obviously doesn't compile
data Shape = Circle Circle | Rectangle Rectangle deriving (Show)
The above leads to the compilation errors
Multiple declarations of ‘Circle’
18 | data Shape = Circle Circle | Rectangle Rectangle deriving (Show)
| ^^^^^^^^^^^^^
...
Multiple declarations of ‘Rectangle’
18 | data Shape = Circle Circle | Rectangle Rectangle deriving (Show)
| ^^^^^^^^^^^^^^^^^^^
How can I declare a type Shape
that would be a union of all possible different shapes (like Circle
or Rectangle
) so that I'm able to use them in subsequent functions like the following?
area :: Shape -> Float
area (Circle _ r) = pi * r * 2
area (Rectangle p1 p2) = abs (x p2 - x p1) * abs (y p2 - y p1)
Upvotes: 1
Views: 116
Reputation: 476740
How can I declare a type
Shape
that would be a union of all possible different shapes (likeCircle
orRectangle
) so that I'm able to use them in subsequent functions like the following?
That would likely not be good design, since if later another person wants to add a shape, then that is not possible. Often one uses a type class [wiki]. A typeclass is to some extent comparable to an interface in Java. Types can be "members" of a typeclass if they implement the methods the typeclass offers.
We can thus for example define a typeclass:
class Shape a where
area :: a -> Float
Then Circle
and Rectangle
can implement this:
instance Shape Circle where
area (Circle _ r) = 2 * pi * r
instance Shape Rectangle where
area (Rectangle p1 p2) = abs (x p2 - x p1) * abs (y p2 - y p1)
Here area
has type area :: Shape a => a -> Float
, it thus means that for every type a
where a
is a "member" of the Shape
typeclass, you can obtain the area. A type class thus provides a form of ad-hoc polymorphism.
Upvotes: 2
Reputation: 119877
data Circle = Circle ... -- one
data Shape = Circle ... -- two
You are trying to define two separate data constructors named Circle
: one is for the data type Circle
and the other is for the data type Shape
. You can't do that in the same module (without some advanced language extensions at least). Rename one of the Circle
s at the right hand side of the =
. The data type at the left-hand side of the =
can still be Circle
, there is no conflict.
Upvotes: 5