Jivan
Jivan

Reputation: 23068

Type reuse in Haskell

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

Answers (2)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476740

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?

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

n. m. could be an AI
n. m. could be an AI

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 Circles 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

Related Questions