Constructor
From HaskellWiki
(Difference between revisions)
(start) |
(added notes) |
||
| (2 intermediate revisions not shown.) | |||
| Line 1: | Line 1: | ||
| + | [[Category:Language]] | ||
'''Constructor''' can mean: | '''Constructor''' can mean: | ||
* Type constructor | * Type constructor | ||
| Line 4: | Line 5: | ||
== Type constructor == | == Type constructor == | ||
| - | A type constructor is used to construct new types from given ones. | + | A [[type]] constructor is used to construct new types from given ones. |
<haskell> | <haskell> | ||
data Tree a = Tip | Node a (Tree a) (Tree a) | data Tree a = Tip | Node a (Tree a) (Tree a) | ||
| Line 11: | Line 12: | ||
== Data constructor == | == Data constructor == | ||
| - | A data constructor groups values together and tags alternatives in an algebraic data type, | + | A data constructor groups values together and tags 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 22: | Line 23: | ||
On the other hand, <hask>Node</hask> contains other data. The types of those data are its parameters. The first one has type <hask>a</hask>, so it's just a value of the parameter type <hask>a</hask>. This one is the value the tree node holds in it. The remaining two are the branches. Each of them have type <hask>Tree a</hask>, naturally. | On the other hand, <hask>Node</hask> contains other data. The types of those data are its parameters. The first one has type <hask>a</hask>, so it's just a value of the parameter type <hask>a</hask>. This one is the value the tree node holds in it. The remaining two are the branches. Each of them have type <hask>Tree a</hask>, naturally. | ||
| - | === | + | ===Data constructors as first class values=== |
| - | Data constructors are not types | + | Data constructors are first class values in Haskell and actually have a [[type]]. For instance, the type of the <hask>Left</hask> constructor of the <hask>Either</hask> data type is: |
| + | <haskell> | ||
| + | Left :: forall b a. a -> Either a b | ||
| + | </haskell> | ||
| + | |||
| + | 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. | ||
| + | |||
| + | |||
| + | === Data constructors are not types=== | ||
| + | As discussed above, they denote values. It is illegal to write <hask>Node a (Node a) (Node a)</hask> there, because the type is <hask>Tree</hask>, not <hask>Node</hask>. | ||
== Deconstructing data constructors == | == Deconstructing data constructors == | ||
| Line 33: | Line 43: | ||
So, the depth of a tip is zero. The depth of a node depends on its branches, but not it's 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. | So, the depth of a tip is zero. The depth of a node depends on its branches, but not it's 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 == | + | == Notes and tips== |
| - | * You can declare a constructor (for both type and data) to be infix, and this can make your code a lot more readable. | + | * 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, <hask>(4, True)</hask> is really a value of the form <hask>(,) 4 True</hask> having the type <hask>(,) Int Bool</hask>, which, too, is written conveniently as <hask>(Int, Bool)</hask> to make it more readable. Incidentally, the empty tuple type <hask>()</hask> with its only value <hask>()</hask> is used throughout, and is called ''unit''. | + | * [[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, <hask>(4, True)</hask> is really a value of the form <hask>(,) 4 True</hask> having the type <hask>(,) Int Bool</hask>, which, too, is written conveniently as <hask>(Int, Bool)</hask> to make it more readable. Incidentally, the empty tuple type <hask>()</hask> with its only value <hask>()</hask> is used throughout, and is called ''unit''. |
| - | * You can, in fact, name the values grouped together, using the record syntax, <haskell> | + | * You can, in fact, name the values grouped together, using the [[record]] syntax, <haskell> |
data Person = Person { name :: String, age :: Int, address :: String } | data Person = Person { name :: String, age :: Int, address :: String } | ||
| - | </haskell> | + | </haskell> so that for a person <hask>p</hask>, you can say <hask>age p</hask> to select his/her age, without resorting to pattern matching. |
| - | so that for a person <hask>p</hask>, you can say <hask>age p</hask> to select his/her age, without resorting to pattern matching. | + | * 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. | ||
Current revision
Constructor can mean:
- Type constructor
- Data constructor
Contents |
1 Type constructor
A type constructor is used to construct new types from given ones.
data Tree a = Tip | Node a (Tree a) (Tree a)
Tree
a
Integer
Maybe String
Tree b
b
a
Tree Int
Tree (Tree Boolean)
2 Data constructor
A data constructor groups values together and tags 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.
On the other hand,Node
a
a
Tree a
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.
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
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
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.
