3The type system defines the following types:
10 - E.g. `[String]`, `[[Number]]`
12 - E.g. `{ foo :: String, bar :: Number }`
14 - E.g. `data Foo a = Foo | Bar String`
16 - E.g. `Number -> String`
17 - E.g. `(Number, Number) -> Number`
18 - Functions can have zero or more arguments
20 - E.g. `forall a. a -> a`
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 `!==`
35str = "Hello, " ++ "World!"
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`
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`
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).
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")
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.
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:
86which would correspond to the Javascript
96Multiple argument functions can be introduced by wrapping the arguments in parentheses, and separating them with commas:
99test1 = \(a, b) -> a + b
105function test1(a, b) {
110In the case of a function with no arguments, the parentheses may be omitted, as follows:
116which would correspond to the Javascript `function test2() { return 100; }`
118Multiple-argument and single-argument syntax can be mixed, as follows:
121test3 = \a (b, c) d -> a + b + c + d
128 return function (b, c) {
129 return function (d) {
130 return a + b + c + d;
136Functions are applied by providing their arguments inside parentheses:
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:
146-- has type Number -> Number -> Number -> Number
147addThree = \a b c -> a + b + c
149-- has type Number -> Number -> Number
152-- has type Number -> Number
161Expressions defined at the top level may have polymorphic types.
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:
174identity :: forall a. a -> a
178Functions may also be polymorphic in row types or type variables with other kinds (see "Kind System"):
181addProps o = o.foo + o.bar
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:
189addProps { foo: 1, bar: 2, baz: 3 }
192but the following does not:
198since the `bar` property is missing.
200Again, a type annotation can be provided if necessary.
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:
211poly :: (forall a. a -> a) -> Boolean
212poly f = (f 0 < 1) == f true
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:
220test = poly (\n -> n + 1)
223since the skolemized type variable `a` does not unify with `Number`.
227For convenience, it is possible to declare a synonym for a type using the `type` keyword. Type synonyms can include type arguments.
232type Foo = { foo :: Number, bar Number }
234addFoo :: Foo -> Number
235addFoo = \o -> o.foo + o.bar
240All types can be inferred, but annotations can optionally be provided.
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.
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