1

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?

hawkeye
  • 34,745
  • 30
  • 150
  • 304
  • 8
    "Types declared in value constructors" makes no sense. They're not types so they're definitely not "types declared in value constructors". They're data constructors. You also can't write the function `surface :: 13 -> 1.2`. – pdexter Jun 14 '16 at 11:07
  • 3
    The syntax for `data` is a historical accident. Use the GADT syntax for a more consistent way to give types to constructors. – augustss Jun 14 '16 at 12:34
  • @augustss ... it's not really an accident - I think GADTs are not even in the standard yet (not that it matters too much) – Random Dev Jun 14 '16 at 13:09
  • instead of concentrating on the `Shape` I would look at what you want to do with them - that is the operations like `surface` - if you want to abstract this you could write functions to collect those into a record (or another data structure) or create a type-class for those - TL;DR: OOP = collect nouns / FP = collect verbs – Random Dev Jun 14 '16 at 13:11
  • 1
    @Carsten It's a historical accident in the sense that it was influenced by other languages at the time of the design, like Miranda, LML, and Orwell. These in turn where influenced by Hope. – augustss Jun 14 '16 at 13:34

1 Answers1

8
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
chi
  • 111,837
  • 3
  • 133
  • 218