4The type system defines the following types:
6- Primitive Types: Number, String, Boolean
20The three primitive types ``String``, ``Number`` and ``Boolean`` correspond to their Javascript equivalents at runtime.
25PureScript arrays correspond to Javascript arrays at runtime, but all elements in an array must have the same type.
30PureScript records correspond to Javascript objects. They may have zero or more named fields, each with their own types.
35Tagged unions consist of one or more constructors, each of which takes zero or more arguments.
37Tagged unions can only be created using their constructors, and deconstructed through pattern matching (see later).
41 data Foo = Foo | Bar String
43 runFoo Foo = "It's a Foo"
44 runFoo (Bar s) = "It's a Bar. The string is " ++ s
46 test = runFoo Foo ++ runFoo (Bar "Test")
48In the example, Foo is a tagged union type which has two constructors. Its first constructor ``Foo`` takes no arguments, and its second ``Bar`` takes one, which must be a String.
50``runFoo`` is an example of pattern matching on a tagged union type to discover its constructor, and the last line shows how to construct values of type ``Foo``.
55Newtypes are like data types introduced with the ``data`` keyword, but are restricted to a single contructor which contains a single argument. Newtypes are introduced with the ``newtype`` keyword::
57 newtype Percentage = Percentage Number
59The representation of a newtype at runtime is the same as the underlying data type. For example, a value of type ``Percentage`` is just a JavaScript number at runtime.
61Newtypes can be assigned their own type class instances, so for example, ``Percentage`` can be given its own ``Show`` instance::
63 instance showPercentage :: Show Percentage where
64 show (Percentage n) = show n ++ "%"
69Functions in PureScript are like their Javascript counterparts, but always have exactly one argument.
74Expressions defined at the top level may have polymorphic types.
80``identity`` is inferred to have (polymorphic) type ``forall t0. t0 -> t0``. This means that for any type ``t0``, ``identity`` can be given a value of type ``t0`` and will give back a value of the same type.
82A type annotation can also be provided::
84 identity :: forall a. a -> a
90Polymorphism is not limited to abstracting over types. Values may also be polymorphic in types with other kinds, such as rows or effects (see "Kind System").
92For example, the following function accesses two properties on a record::
94 addProps o = o.foo + o.bar
96The inferred type of ``addProps`` is::
98 forall r. { foo :: Number, bar :: Number | r } -> Number
100Here, the type variable ``r`` has kind ``# *`` - it represents a `row` of `types`. It can be instantiated with any row of named types.
102In other words, ``addProps`` accepts any record which has properties ``foo`` and ``bar``, and *any other record properties*.
104Therefore, the following application compiles::
106 addProps { foo: 1, bar: 2, baz: 3 }
108even though the type of ``addProps`` does not mention the property ``baz``. However, the following does not compile::
112since the ``bar`` property is missing.
117It is also possible for the ``forall`` quantifier to appear on the left of a function arrow, inside types record fields and data constructors, and in type synonyms.
119In most cases, a type annotation is necessary when using this feature.
121As an example, we can pass a polymorphic function as an argument to another function::
123 poly :: (forall a. a -> a) -> Boolean
124 poly f = (f 0 < 1) == f true
126Notice that the polymorphic function's type argument is instantiated to both ``Number`` and ``Boolean``.
128An argument to ``poly`` must indeed be polymorphic. For example, the following fails::
130 test = poly (\n -> n + 1)
132since the skolemized type variable ``a`` does not unify with ``Number``.
137A row of types represents an unordered collection of named types without duplicates.
139Rows have kind ``# k`` for some kind ``k``, and so values do not have types which are rows. Rather, rows can be used in type signatures to define record types or other type where labelled, unordered types are useful.
141To denote a closed row, separate the fields with commas, with each label separated from its type with a double colon::
143 (name :: String, age :: Number)
145It may be necessary, depending on the context, to surround a row in parentheses.
147To denote an open row (i.e. one which may unify with another row to add new fields), separate the specified terms from a row variable by a pipe::
149 (name :: String, age :: Number | r)
154For convenience, it is possible to declare a synonym for a type using the ``type`` keyword. Type synonyms can include type arguments.
158 type Foo = { foo :: Number, bar :: Number }
160 addFoo :: Foo -> Number
161 addFoo = \o -> o.foo + o.bar
166Polymorphic types may be predicated on one or more ``constraints``. See the chapter on type classes for more information.
171Most types can be inferred (not including Rank N Types and constrained types), but annotations can optionally be provided using a double-colon::
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list