git.iko.soy/rowtype-yoga/purescript-native
on 64bd2db help sign in
248 lines 6.4 kB history raw
1## Type System
3The type system defines the following types:
5- Primitive Types
6 - Number
7 - String
8 - Boolean
9- Arrays
10 - E.g. `[String]`, `[[Number]]`
11- Records
12 - E.g. `{ foo :: String, bar :: Number }`
13- Tagged Unions
14 - E.g. `data Foo a = Foo | Bar String`
15- Functions
16 - E.g. `Number -> String`
17 - E.g. `(Number, Number) -> Number`
18 - Functions can have zero or more arguments
19- Polymorphic types
20 - E.g. `forall a. a -> a`
22## Primitive Types
24The three primitive types `String`, `Number` and `Boolean` correspond to their Javascript equivalents at runtime.
26PureScript supports the same binary and unary operations on primitive types as Javascript, with the following exceptions:
28- String concatenation is denoted `++` to differentiate it from numeric addition, `+`
29- PureScript's `==` and `!=` correspond to Javascript's strong equality tests `===` and `!==`
31Examples:
33```haskell
34num = 1 + 2 * 3
35str = "Hello, " ++ "World!"
36bool = 1 > 2 || true
37```
39## Arrays
41PureScript arrays correspond to Javascript arrays at runtime, but all elements must have the same type.
43Array literals look like Javascript array literals: `[1, 2, 3]`
45Array elements can be read using array index notation `arr !! index`
47## Records
49PureScript records correspond to Javascript objects.
51Record literals look like Javascript object literals: `{ foo: "Foo" }`
53Properties can be read by using dot notation: `o.foo`
55## Tagged Unions
57Tagged unions consist of one or more constructors, each of which takes zero or one arguments.
59Tagged unions can only be created using their constructors, and deconstructed through pattern matching (see later).
61For example:
63```haskell
64data Foo a = Foo | Bar String
66runFoo Foo = "It's a Foo"
67runFoo (Bar s) = "It's a Bar. The string is " ++ s
69test = runFoo Foo ++ runFoo (Bar "Test")
70```
72In the example, Foo is a tagged union type which has two constructors. It's first constructor `Foo` takes no argument, and it's second `Bar` takes one, which must be a String.
74`runFoo` is an example of pattern matching on a tagged union type to discover its constructor, and the last line shows how `Foo`s are constructed.
76## Functions
78Functions in PureScript can have zero or more arguments in general, just like in Javascript.
80Functions are introduced by using a backslash followed by a list of argument names:
82```haskell
83test1 = \a b -> a + b
84```
86which would correspond to the Javascript
88```javascript
89function test1(a) {
90 return function (b) {
91 return a + b;
92 }
94```
96Multiple argument functions can be introduced by wrapping the arguments in parentheses, and separating them with commas:
98```haskell
99test1 = \(a, b) -> a + b
100```
102which generates
104```javascript
105function test1(a, b) {
106 return a + b;
108```
110In the case of a function with no arguments, the parentheses may be omitted, as follows:
112```haskell
113test2 = \ -> 100
114```
116which would correspond to the Javascript `function test2() { return 100; }`
118Multiple-argument and single-argument syntax can be mixed, as follows:
120```haskell
121test3 = \a (b, c) d -> a + b + c + d
122```
124which generates
126```javascript
127function test3(a) {
128 return function (b, c) {
129 return function (d) {
130 return a + b + c + d;
131 }
132 }
134```
136Functions are applied by providing their arguments inside parentheses:
138```haskell
139test1(1, 2, 3)
140test2()
141```
143A special case is made in the case of functions with one argument. These functions can be applied without parentheses, and function application associates to the left:
145```haskell
146-- has type Number -> Number -> Number -> Number
147addThree = \a b c -> a + b + c
149-- has type Number -> Number -> Number
150addThree 1
152-- has type Number -> Number
153addThree 1 2
155-- has type Number
156addThree 1 2 3
157```
159## Polymorphic Types
161Expressions defined at the top level may have polymorphic types.
163Here is an example:
165```haskell
166identity x = x
167```
169`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.
171A type annotation can also be provided:
173```haskell
174identity :: forall a. a -> a
175identity x = x
176```
178Functions may also be polymorphic in row types or type variables with other kinds (see "Kind System"):
180```haskell
181addProps o = o.foo + o.bar
182```
184Here, `addProps` is inferred to have type `forall r. { foo :: Number, bar :: Number | r } -> Number`. That is, it can take any type which has properties `Foo` and `Bar`, and *any other record properties*.
186So, the following compiles:
188```haskell
189addProps { foo: 1, bar: 2, baz: 3 }
190```
192but the following does not:
194```haskell
195addProps { foo: 1 }
196```
198since the `bar` property is missing.
200Again, a type annotation can be provided if necessary.
202## Rank N Types
204It 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.
206In most cases, a type annotation is necessary when using this feature.
208As an example, we can pass a polymorphic function as an argument to another function:
210```haskell
211poly :: (forall a. a -> a) -> Boolean
212poly f = (f 0 < 1) == f true
213```
215Notice that the polymorphic function's type argument is instantiated to both `Number` and `Boolean`.
217An argument to `poly` must indeed be polymorphic. For example, the following fails:
219```haskell
220test = poly (\n -> n + 1)
221```
223since the skolemized type variable `a` does not unify with `Number`.
225## Type Synonyms
227For convenience, it is possible to declare a synonym for a type using the `type` keyword. Type synonyms can include type arguments.
229For example:
231```haskell
232type Foo = { foo :: Number, bar Number }
234addFoo :: Foo -> Number
235addFoo = \o -> o.foo + o.bar
236```
238## Type Inference
240All types can be inferred, but annotations can optionally be provided.
242## Kind System
244There are two primitive kinds, the kind `*` of types and the kind `!` of effects.
246For each kind `k` there is also a kind `# k` of rows, with types of kind `k`. For example `# *` is the kind of rows of types, as used to define records, and `# !` is the kind of rows of effects, used to define the monad `Eff` of extensible effects.
248Higher kinded types are also supported. That is, a type variable can refer to not only a type or a row, but a type constructor, or row constructor etc.