Suppose I have the following value constructor:
data Shape = Circle Float Float Float | Rectangle Float Float Float Float
Now I can run:
ghci> :t Circle
Circle :: Float -> Float -> Float -> Shape
Now I can write a type declaration
surface :: Shape -> Float
But I can't type a type declaration
surface :: Circle -> Float
This is because "Circle
is not a type, Shape
is"
My question is: Why are types declared in value constructors not types in Haskell?
data Shape = Circle Float Float Float | Rectangle Float Float Float Float
Shape
is a type (and a type constructor). Float
is another type.
Circle
and Rectangle
are the value constructors for type Shape
.
I guess that your confusion comes from OOP subtyping -- note that Haskell has no analogous to that. The above does not declare two types Circle
and Rectangle
to be subtypes of Shape
.
Using some advanced extensions like GADTs
you can actually write something like foo :: Circle -> Float
meaning that the argument is a Shape
value which has been constructed as a Circle
. This requires some type-level techniques.
Alternatively, a plain Haskell approach could be
data Circle = Circle Float Float Float
data Rectangle = Rectangle Float Float Float Float
data Shape = Scircle Circle | Srectangle Rectangle