2

Reading through a book I came across Haskell Bool Type which is

data Bool = True | False

As I understand in this case True and False are values and the expression of below type is valid

c = True

Later on, when I wanted to create a new type I forgot to name the Value constructor and created the following type.

data Cartesian2D = Double Double

In this case, Haskell (GHCI) did not complain.

But when I tried to construct a value like

x = 1.0 2.0 

and

x = Double Double

in both cases, Haskell returned an error.

In this case,

  1. Is the type Cartesian2D valid?

  2. if the type is not valid, why did Haskell not complain when I was constructing the type? but only informed me while constructing a value of the type.

1 Answer 1

11

Data constructors like True and type constructors like Bool exist in separate namespaces. True is an example of a nullary constructor, taking no arguments. As such, the definition

data Cartesian2D = Double Double

defines a type constructor named Cartesian2D and a unary data constructor named Double. Non-nullary data constructors behave much like functions, taking arguments to return a value of their associated type. Here, Double behaves like a function of type Double -> Cartesian2D (again, note that the type constructor Double and the type constructor Double are distinct).

x = Double 1.0
y = Double 2.0

To create a "real" Cartesian point type that stores two doubles, try something like

data Cartesian2D = Point Double Double

which defines a data constructor Point that takes two values of type Double to create a value of type Cartesian2D.


If you are at all bothered by the fact that nullary data constructors are somehow "special" in not behaving like functions (i.e., you don't have to call True, it just is a value), you can think of nullary constructors as being shorthand for unary constructors that take a dummy argument of type ():

True :: Bool

is short for

True () :: () -> Bool

which would always have to be used as True () otherwise.

Sign up to request clarification or add additional context in comments.

6 Comments

Thanks! I guess the point here is that when I declared data Cartesian2D = Double Double the first Double is the name of the value constructor instead of the Double type. Why does haskell allow name of value constructor that matches an existing type? This can cause some confusion.
Also when you mentioned that Bool exists in a separate namespace, what namespace are you talking about?
(again, note that the type constructor Double and the type constructor Double are distinct). -- this is exactly the sort of confusion I am talking about.
It's convenient in some cases to reuse the type name as the name of a data constructor for the same type, e.g., data Point = Point Double Double. The separate namespaces are what allow you to reuse the name: the language can always tell from context whether any given use of Point refers to the type or the data constructor.
@working When there is only one constructor, it is very common to name the constructor exactly as the type, since it's easier to remember which type has which constructor, and vice versa.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.