consider the following
data Point=Point{x::Float,y::Float}
data Shape=Circle{centre::Point,radius::Float}
|Rectangle {uleft::Point,bRight::Point}
Here the type Shape is a coproduct of two types Circle and Rectangle. I may want to reuse the types Circle and Rectangle elsewhere. So it would be useful to do this instead:
data Point=Point{x::Float,y::Float}
data Circle=Circle{centre::Point,radius::Float}
data Rectangle=Rectangle {uleft::Point,bRight::Point}
data Shape =Circle | Rectangle
but I get a compilation error when I do this: Circle is declared twice. Whats the correct syntax for attempting this, or this not possible?
The coproduct of types in Haskell is commonly denoted by Either
:
data Either a b = Left a | Right b
type Shape = Either Circle Rectangle
-- so you have shapes as either Left c for some Circle c
-- or Right r for some Rectangle r
This works quite nicely, although for technical reasons it isn't exactly a coproduct. Another common way would be to define a type like so:
data Shape = CircleShape Circle | RectangleShape Rectangle
so that CircleShape :: Circle -> Shape
and RectangleShape :: Rectangle -> Shape
are your two injections.
It's wrong to say as you do in your question that the original Shape
is a coproduct of types Circle
and Rectangle
, because the latter two aren't types. If you want to set things up so that Circle p r
is both a value of type Circle
and a value of type Shape
, then that's really contrary to the spirit of Haskell's type system (although something similar might be possible with sufficiently many type system extensions).
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