git.iko.soy/rowtype-yoga/purescript-native
on 33db511 help sign in
173 lines 5.7 kB history raw
1Types
2=====
4The type system defines the following types:
6- Primitive Types: Number, String, Boolean
7- Arrays
8- Records
9- Tagged Unions
10- Newtypes
11- Functions
12- Polymorphic Types
13- Constrained Types
14- Type Synonyms
15- Rows
17Primitive Types
18---------------
20The three primitive types ``String``, ``Number`` and ``Boolean`` correspond to their Javascript equivalents at runtime.
22Arrays
23------
25PureScript arrays correspond to Javascript arrays at runtime, but all elements in an array must have the same type.
27Records
28-------
30PureScript records correspond to Javascript objects. They may have zero or more named fields, each with their own types.
32Tagged Unions
33-------------
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).
39For example::
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``.
52Newtypes
53--------
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 ++ "%"
66Functions
67---------
69Functions in PureScript are like their Javascript counterparts, but always have exactly one argument.
71Polymorphic Types
72-----------------
74Expressions defined at the top level may have polymorphic types.
76Here is an example::
78 identity x = x
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
85 identity x = x
87Row Polymorphism
88----------------
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::
110 addProps { foo: 1 }
112since the ``bar`` property is missing.
114Rank N Types
115------------
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``.
134Rows
135----
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)
151Type Synonyms
152-------------
154For convenience, it is possible to declare a synonym for a type using the ``type`` keyword. Type synonyms can include type arguments.
156For example::
158 type Foo = { foo :: Number, bar :: Number }
160 addFoo :: Foo -> Number
161 addFoo = \o -> o.foo + o.bar
163Constrained Types
164-----------------
166Polymorphic types may be predicated on one or more ``constraints``. See the chapter on type classes for more information.
168Type Annotations
169----------------
171Most types can be inferred (not including Rank N Types and constrained types), but annotations can optionally be provided using a double-colon::
173 one = 1 :: Number