# Constructor

### From HaskellWiki

(Difference between revisions)

Uchchwhash (Talk | contribs) (added notes) |
Iceland jack (Talk | contribs) (→Deconstructing data constructors) |
||

(4 intermediate revisions by 2 users not shown) | |||

Line 3: | Line 3: | ||

* Type constructor | * Type constructor | ||

* Data constructor | * Data constructor | ||

+ | |||

+ | A <hask>data</hask> declaration introduces one or more ''type'' constructors and one or more ''value'' constructors for each of the type constructors. | ||

== Type constructor == | == Type constructor == | ||

− | A [[type]] constructor is | + | A '''[[type]] constructor''' may have zero or more arguments, if it has zero arguments it is called a ''nullary'' type constructor (or simply a '''type'''). An example of a nullary type constructor <hask>Bool</hask> with two nullary data constructors <hask>True</hask> and <hask>False</hask> |

+ | |||

+ | <haskell> | ||

+ | data Bool = True | False | ||

+ | </haskell> | ||

+ | |||

+ | An example of a ''unary'' type constructor <haskell>Tree</haskell> | ||

+ | |||

<haskell> | <haskell> | ||

data Tree a = Tip | Node a (Tree a) (Tree a) | data Tree a = Tip | Node a (Tree a) (Tree a) | ||

</haskell> | </haskell> | ||

+ | |||

illustrates how to define a data type with type constructors (and data constructors at the same time). The type constructor is named <hask>Tree</hask>, but a tree of what? Of any specific type <hask>a</hask>, be it <hask>Integer</hask>, <hask>Maybe String</hask>, or even <hask>Tree b</hask>, in which case it will be a tree of tree of <hask>b</hask>. The data type is polymorphic (and <hask>a</hask> is a type variable that is to be substituted by a specific type). So when used, the values will have types like <hask>Tree Int</hask> or <hask>Tree (Tree Boolean)</hask>. | illustrates how to define a data type with type constructors (and data constructors at the same time). The type constructor is named <hask>Tree</hask>, but a tree of what? Of any specific type <hask>a</hask>, be it <hask>Integer</hask>, <hask>Maybe String</hask>, or even <hask>Tree b</hask>, in which case it will be a tree of tree of <hask>b</hask>. The data type is polymorphic (and <hask>a</hask> is a type variable that is to be substituted by a specific type). So when used, the values will have types like <hask>Tree Int</hask> or <hask>Tree (Tree Boolean)</hask>. | ||

== Data constructor == | == Data constructor == | ||

− | A data constructor | + | A '''data constructor''' (or '''value constructor''') can have zero or more arguments where a data constructor taking zero arguments is called a ''nullary data constructor'' or simply a '''constant'''. They group values together and tag alternatives in an [[algebraic data type]], |

<haskell> | <haskell> | ||

data Tree a = Tip | Node a (Tree a) (Tree a) | data Tree a = Tip | Node a (Tree a) (Tree a) | ||

Line 37: | Line 47: | ||

== Deconstructing data constructors == | == Deconstructing data constructors == | ||

All a data constructor does is holding values together. But you want to separate them if you want to use them. This is done via [[pattern matching]], | All a data constructor does is holding values together. But you want to separate them if you want to use them. This is done via [[pattern matching]], | ||

+ | |||

<haskell> | <haskell> | ||

− | depth Tip = 0 | + | depth Tip = 0 |

depth (Node _ l r) = 1 + max (depth l) (depth r) | depth (Node _ l r) = 1 + max (depth l) (depth r) | ||

</haskell> | </haskell> | ||

− | So, the depth of a tip is zero. The depth of a node depends on its branches, but not | + | |

+ | So, the depth of a tip is zero. The depth of a node depends on its branches, but not its content. See how the constructor in the left hand side names its parts? we don't need the content so we don't name it (using <hask>_</hask>). The left branch is named <hask>l</hask>, the right <hask>r</hask>, allowing us to use these values in the right hand side. | ||

== Notes and tips== | == Notes and tips== | ||

Line 51: | Line 63: | ||

* Sometimes you need a little editting or checking when constructing your data. If you do, check [[smart constructors]] | * Sometimes you need a little editting or checking when constructing your data. If you do, check [[smart constructors]] | ||

* Sometimes you do not want the user of your library to group arbitrary values together. This is achieved by ''hiding'' your constructor (not mentioning it in the export list of the module), creating an [[abstract data type]] as a result. Along with smart constructors mentioned above, one can achieve encapsulation. | * Sometimes you do not want the user of your library to group arbitrary values together. This is achieved by ''hiding'' your constructor (not mentioning it in the export list of the module), creating an [[abstract data type]] as a result. Along with smart constructors mentioned above, one can achieve encapsulation. | ||

+ | |||

+ | == References == | ||

+ | * [http://www.cs.cmu.edu/~rwh/smlbook/book.pdf Programming in Standard ML]: Chapter 10 (Concrete Data Types) |

## Latest revision as of 16:57, 29 December 2013

**Constructor** can mean:

- Type constructor
- Data constructor

data

*type*constructors and one or more

*value*constructors for each of the type constructors.

## Contents |

## [edit] 1 Type constructor

A**type constructor**may have zero or more arguments, if it has zero arguments it is called a

*nullary*type constructor (or simply a

**type**). An example of a nullary type constructor

Bool

True

False

data Bool = True | False

*unary*type constructor

Tree

data Tree a = Tip | Node a (Tree a) (Tree a)

Tree

a

Integer

Maybe String

Tree b

b

a

Tree Int

Tree (Tree Boolean)

## [edit] 2 Data constructor

A **data constructor** (or **value constructor**) can have zero or more arguments where a data constructor taking zero arguments is called a *nullary data constructor* or simply a **constant**. They group values together and tag alternatives in an algebraic data type,

data Tree a = Tip | Node a (Tree a) (Tree a)

Tip

Node

Tree a

Tip

Node

Tip

Tip

Bool

data Bool = True | False

and for all practical purposes you can just think of them as *constants* belonging to a type.

Node

a

a

Tree a

### [edit] 2.1 Data constructors as first class values

Data constructors are first class values in Haskell and actually have a type. For instance, the type of theLeft

Either

Left :: forall b a. a -> Either a b

As first class values, they may be passed to functions, held in a list, be data elements of other algebraic data types and so forth.

### [edit] 2.2 Data constructors are not types

As discussed above, they denote values. It is illegal to writeNode a (Node a) (Node a)

Tree

Node

## [edit] 3 Deconstructing data constructors

All a data constructor does is holding values together. But you want to separate them if you want to use them. This is done via pattern matching,

depth Tip = 0 depth (Node _ l r) = 1 + max (depth l) (depth r)

_

l

r

## [edit] 4 Notes and tips

- You can declare a constructor (for both type and data) to be an infix operator, and this can make your code a lot more readable. However, for alphanumeric names, the names of both the type constructor and the data constructor(s) must start with an uppercase letter.
- Tuples are a built in feature of the syntax but are plain old algebraic data types! They have only one constructor though. Having the same name as their types (don't freak out, it's just a matter of convenience, as the type constructors and the data constructors have separate namespaces). So, is really a value of the form(4, True)having the type(,) 4 True, which, too, is written conveniently as(,) Int Boolto make it more readable. Incidentally, the empty tuple type(Int, Bool)with its only value()is used throughout, and is called()
*unit*. - You can, in fact, name the values grouped together, using the record syntax, so that for a person
data Person = Person { name :: String, age :: Int, address :: String }

, you can saypto select his/her age, without resorting to pattern matching.age p - Sometimes you need a little editting or checking when constructing your data. If you do, check smart constructors
- Sometimes you do not want the user of your library to group arbitrary values together. This is achieved by
*hiding*your constructor (not mentioning it in the export list of the module), creating an abstract data type as a result. Along with smart constructors mentioned above, one can achieve encapsulation.

## [edit] 5 References

- Programming in Standard ML: Chapter 10 (Concrete Data Types)