@@ -56,16 +56,18 @@ PureScript can also be seen as a trade-off between a theoretically ideal languag
57The following code defines a `Person` data type and a function to generate a string representation for a `Person`:
57The following code defines a `Person` data type and a function to generate a string representation for a `Person`:
59− data Person = Person
60+data Person = Person
60− { name :: String
61+{ name :: String
61− ; age :: Number
62+; age :: Number
64− extern itoa :: Number -> String
65+extern itoa :: Number -> String
66− showPerson :: Person -> String
67+showPerson :: Person -> String
67− showPerson = \p -> case p of
68+showPerson = \p -> case p of
68− Person o -> o.name ++ ", aged " ++ itoa(o.age)
69+Person o -> o.name ++ ", aged " ++ itoa(o.age)
70Line by line, this reads as follows:
72Line by line, this reads as follows:
@@ -77,20 +79,22 @@ Line by line, this reads as follows:
78The generated Javascript looks like this:
80The generated Javascript looks like this:
80− var Person = function (value) {
83+var Person = function (value) {
81− return { ctor: 'Person', value: value };
84+return { ctor: 'Person', value: value };
84− var showPerson = function (p) {
87+var showPerson = function (p) {
85− return (function (_0) {
88+return (function (_0) {
86− if (_0.ctor === "Person") {
89+if (_0.ctor === "Person") {
87− var _1 = _0.value;
90+ var _1 = _0.value;
88− var o = _1;
91+ var o = _1;
89− return o.name ++ ", aged " ++ itoa(o.age);
92+ return o.name ++ ", aged " ++ itoa(o.age);
91− throw "Failed pattern match";
94+throw "Failed pattern match";
95## Type System
99## Type System
@@ -124,9 +128,11 @@ PureScript supports the same binary and unary operations on primitive types as J
127− num = 1 + 2 * 3
132+num = 1 + 2 * 3
128− str = "Hello, " ++ "World!"
133+str = "Hello, " ++ "World!"
129− bool = 1 > 2 || true
134+bool = 1 > 2 || true
@@ -152,14 +158,16 @@ Tagged unions can only be created using their constructors, and deconstructed th
153For example:
159For example:
155− data Foo a = Foo | Bar String
162+data Foo a = Foo | Bar String
157− runFoo = \foo -> case foo of
164+runFoo = \foo -> case foo of
158− Foo -> "It's a Foo"
165+Foo -> "It's a Foo"
159− Bar s -> "It's a Bar. The string is " ++ s
166+Bar s -> "It's a Bar. The string is " ++ s
161− runFoo Foo ++ runFoo (Bar "Test")
168+runFoo Foo ++ runFoo (Bar "Test")
163In 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.
171In 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.
165`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.
173`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.
@@ -170,34 +178,42 @@ Functions in TypeScript can have zero or more arguments in general, just like in
171Functions are introduced by using a backslash followed by a comma separated list of argument names:
179Functions are introduced by using a backslash followed by a comma separated list of argument names:
173− test1 = \a, b, c -> a + b + c
182+test1 = \a, b, c -> a + b + c
175which would correspond to the Javascript `function test1(a, b, c) { return a + b + c; }`
185which would correspond to the Javascript `function test1(a, b, c) { return a + b + c; }`
177A function taking no arguments would look like this:
187A function taking no arguments would look like this:
179− test2 = \ -> 100
190+test2 = \ -> 100
181which would correspond to the Javascript `function test2() { return 100; }`
193which would correspond to the Javascript `function test2() { return 100; }`
183Functions are applied by providing their arguments inside parentheses:
195Functions are applied by providing their arguments inside parentheses:
185− test1(1, 2, 3)
198+test1(1, 2, 3)
188A 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:
202A 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:
190− -- has type Number -> Number -> Number -> Number
205+-- has type Number -> Number -> Number -> Number
191− addThree = \a -> \b -> \c -> a + b + c
206+addThree = \a -> \b -> \c -> a + b + c
193− -- has type Number -> Number -> Number
208+-- has type Number -> Number -> Number
194− addThree 1
209+addThree 1
196− -- has type Number -> Number
211+-- has type Number -> Number
197− addThree 1 2
212+addThree 1 2
199− -- has type Number
214+-- has type Number
200− addThree 1 2 3
215+addThree 1 2 3
202## Polymorphic Types
218## Polymorphic Types
@@ -205,28 +221,38 @@ Expressions defined at the top level may have polymorphic types.
206Here is an example:
222Here is an example:
208− identity = \x -> x
225+identity = \x -> x
210`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.
228`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.
212A type annotation can also be provided:
230A type annotation can also be provided:
214− identity :: forall a. a -> a
233+identity :: forall a. a -> a
215− identity = \x -> x
234+identity = \x -> x
217Functions may also be polymorphic in row types or type variables with other kinds (see "Kind System"):
237Functions may also be polymorphic in row types or type variables with other kinds (see "Kind System"):
219− addProps = \o -> o.foo + o.bar
240+addProps = \o -> o.foo + o.bar
221Here, `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*.
243Here, `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*.
223So, the following compiles:
245So, the following compiles:
225− addProps { foo: 1, bar: 2, baz: 3 }
248+addProps { foo: 1, bar: 2, baz: 3 }
227but the following does not:
251but the following does not:
229− addProps { foo: 1 }
254+addProps { foo: 1 }
231since the `bar` property is missing.
257since the `bar` property is missing.
@@ -246,13 +272,17 @@ Syntax is whitespace sensitive. The general rule of thumb is that declarations w
247That is, the following is valid:
273That is, the following is valid:
249− foo = bar(x) +
276+foo = bar(x) +
252But this is not:
280But this is not:
254− foo = bar(x) +
283+foo = bar(x) +
257## Do Notation
287## Do Notation
@@ -271,38 +301,46 @@ The following types of statement are supported:
272Here is an example of a power function defined using a block:
302Here is an example of a power function defined using a block:
274− pow = \n, p -> do
305+pow = \n, p -> do
275− var m = n
306+ var m = n
276− for i <- 0 until p:
307+ for i <- 0 until p:
277− m = m * n
308+ m = m * n
278− return m
309+ return m
280Blocks enable local mutation of their variables, but mutation is not allowed in general. The type system prevents mutable variables from escaping their scope.
312Blocks enable local mutation of their variables, but mutation is not allowed in general. The type system prevents mutable variables from escaping their scope.
282That is, while the example above is valid, the following does not compile:
314That is, while the example above is valid, the following does not compile:
284− incr = \n -> do
317+incr = \n -> do
285− n = n + 1
318+ n = n + 1
286− return n
319+ return n
288The variable `n` is not mutable, and so the assignment in the first line of the `do` block is not allowed.
322The variable `n` is not mutable, and so the assignment in the first line of the `do` block is not allowed.
290This function can be rewritten as follows:
324This function can be rewritten as follows:
292− incr = \n -> do
327+incr = \n -> do
293− var m = n
328+ var m = n
294− m = m + 1
329+ m = m + 1
295− return m
330+ return m
297## For Loops
333## For Loops
299For loops look like this:
335For loops look like this:
301− total = do
338+total = do
302− var n = 0
339+ var n = 0
303− for i <- 0 until 10:
340+ for i <- 0 until 10:
304− n = n + i
341+ n = n + i
305− return n
342+ return n
307The bounds `0` and `10` are inclusive and exclusive respectively.
345The bounds `0` and `10` are inclusive and exclusive respectively.
@@ -310,38 +348,44 @@ The bounds `0` and `10` are inclusive and exclusive respectively.
311For each loops loop over the elements in an array using the `Object.forEach` method. A polyfill may be required for some browsers:
349For each loops loop over the elements in an array using the `Object.forEach` method. A polyfill may be required for some browsers:
313− total = \arr -> do
352+total = \arr -> do
314− var n = 0
353+ var n = 0
315− foreach i in arr:
354+ foreach i in arr:
316− n = n + i
355+ n = n + i
317− return n
356+ return n
319## While Loops
359## While Loops
321The syntax of a while loop is similar to a foreach loop:
361The syntax of a while loop is similar to a foreach loop:
323− log2 = \n -> do
364+log2 = \n -> do
324− var count = 0
365+ var count = 0
325− var m = n
366+ var m = n
326− while m > 1:
367+ while m > 1:
327− m = m / 2
368+ m = m / 2
328− count = count + 1
369+ count = count + 1
329− return count
370+ return count
331## If-Then-Else Statements
373## If-Then-Else Statements
333Else branches are optional, and may contain further `if` statements, just as in Javascript:
375Else branches are optional, and may contain further `if` statements, just as in Javascript:
335− collatz = \n -> do
378+collatz = \n -> do
336− var count = 0
379+ var count = 0
337− var m = n
380+ var m = n
338− while m > 1:
381+ while m > 1:
339− if m % 2 == 0:
382+ if m % 2 == 0:
340− m = m / 2
383+ m = m / 2
342− m = m * 3 + 1
385+ m = m * 3 + 1
343− count = count + 1
386+ count = count + 1
344− return count
387+ return count
346## If-Then-Else Expressions
390## If-Then-Else Expressions
@@ -349,7 +393,9 @@ The `if`, `then` and `else` keywords can also be used to create conditional expr
350For example,
394For example,
352− conditional = if 2 > 1 then "ok" else "oops"
397+conditional = if 2 > 1 then "ok" else "oops"
354## Pattern Matching
400## Pattern Matching
@@ -357,10 +403,12 @@ Pattern matching deconstructs a value to bring zero or more expressions into sco
358Pattern matches have the following general form
404Pattern matches have the following general form
360− case value of
407+case value of
361− pattern -> result
408+ pattern -> result
363− pattern -> result
410+ pattern -> result
365The following pattern types are supported:
413The following pattern types are supported:
@@ -378,31 +426,37 @@ Patterns need not be exhaustive. A pattern match failed exception will be thrown
379The wilcard `_` matches any input and brings nothing into scope:
427The wilcard `_` matches any input and brings nothing into scope:
381− case x of
430+case x of
384## Literal Patterns
434## Literal Patterns
386Literal patterns are provided to match on primitives:
436Literal patterns are provided to match on primitives:
388− case booleanValue of
439+case booleanValue of
389− true -> 0
440+ true -> 0
390− false -> 1
441+ false -> 1
392− case stringValue of
443+case stringValue of
393− "Foo" -> 0
444+ "Foo" -> 0
396− case numericValue of
447+case numericValue of
400## Variable Pattern
452## Variable Pattern
402A variable pattern matches any input and binds that input to its name:
454A variable pattern matches any input and binds that input to its name:
404− case foo(x) of
457+case foo(x) of
405− result -> bar(result)
458+ result -> bar(result)
407## Array Patterns
461## Array Patterns
@@ -410,10 +464,12 @@ Array patterns match an input which is an array, and bring its elements into sco
411For example:
465For example:
413− f = \arr -> case arr of
468+f = \arr -> case arr of
414− [x] -> x
469+ [x] -> x
415− [x, y : xs] -> x * y + f(xs)
470+ [x, y : xs] -> x * y + f(xs)
418Here, the first pattern only matches arrays of length one, and brings the first element of the array into scope.
474Here, the first pattern only matches arrays of length one, and brings the first element of the array into scope.
@@ -423,9 +479,11 @@ The second pattern matches arrays with two or more elements, and brings the firs
424Record patterns match an input which is a record, and bring its properties into scope.
480Record patterns match an input which is a record, and bring its properties into scope.
426− f = \o -> case o of
483+f = \o -> case o of
427− { foo = "Foo" } -> o.bar
484+ { foo = "Foo" } -> o.bar
430## Nested Patterns
488## Nested Patterns
@@ -433,54 +491,65 @@ The patterns above can be combined to create larger patterns.
434For example:
492For example:
436− f = \o -> case o of
495+f = \o -> case o of
437− { arr = [x:_], take = "car" } -> x
496+ { arr = [x:_], take = "car" } -> x
438− { arr = [_,x:_], take = "cadr" } -> x
497+ { arr = [_,x:_], take = "cadr" } -> x
441## Named Patterns
501## Named Patterns
443Named patterns bring additional names into scope when using nested patterns. Any pattern can be named by using the `@` symbol:
503Named patterns bring additional names into scope when using nested patterns. Any pattern can be named by using the `@` symbol:
445− f = \arr -> case arr of
506+f = \arr -> case arr of
446− a@[_,_:_] -> a
507+ a@[_,_:_] -> a
449Here, in the first pattern, any array with two or more elements will be matched and bound to the variable `a`.
511Here, in the first pattern, any array with two or more elements will be matched and bound to the variable `a`.
453Guards are used to impose additional constraints inside a pattern using boolean-valued expressions, and are introduced with a pipe after the pattern:
515Guards are used to impose additional constraints inside a pattern using boolean-valued expressions, and are introduced with a pipe after the pattern:
455− evens = \arr -> case arr of
518+evens = \arr -> case arr of
457− [x:xs] | x % 2 == 0 -> 1 + evens xs
520+ [x:xs] | x % 2 == 0 -> 1 + evens xs
458− [_:xs] -> evens xs
521+ [_:xs] -> evens xs
460## Type Synonyms
524## Type Synonyms
462For convenience, it is possible to declare a synonym for a type using the `type` keyword. Type synonyms can include type arguments.
526For convenience, it is possible to declare a synonym for a type using the `type` keyword. Type synonyms can include type arguments.
464For example:
528For example:
466− type Foo = { foo :: Number, bar Number }
531+type Foo = { foo :: Number, bar Number }
468− addFoo :: Foo -> Number
533+addFoo :: Foo -> Number
469− addFoo = \o -> o.foo + o.bar
534+addFoo = \o -> o.foo + o.bar
471## Record Updates
536## Record Updates
473Properties on records can be updated using the following syntax: `o { key = value, ..., key = value }`
538Properties on records can be updated using the following syntax: `o { key = value, ..., key = value }`
475For example, the following function increments the `foo` property on its argument:
540For example, the following function increments the `foo` property on its argument:
477− incr = \o -> o { foo = o.foo + 1 }
543+incr = \o -> o { foo = o.foo + 1 }
479The generated Javascript assumes the existence of a method called `Object.extend` such that `Object.extend(o, p)` takes an object `o` and generates a shallow copy of `o` including the properties of `p`. A simple JQuery implementation of this specification is
546The generated Javascript assumes the existence of a method called `Object.extend` such that `Object.extend(o, p)` takes an object `o` and generates a shallow copy of `o` including the properties of `p`. A simple JQuery implementation of this specification is
481− Object.prototype.extend = function(o, p) {
549+Object.prototype.extend = function(o, p) {
482− return $.extend({}, o, p);
550+ return $.extend({}, o, p);
485## Operators
554## Operators
@@ -488,31 +557,40 @@ In addition to the standard operators, user-defined infix operators can be creat
489E.g. to create a synonym for string concatenation:
558E.g. to create a synonym for string concatenation:
491− (<>) = \s1 -> \s2 -> s1 ++ s2
561+(<>) = \s1 -> \s2 -> s1 ++ s2
493− greeting = "Hello" <> "World!"
563+greeting = "Hello" <> "World!"
495Regular functions can be used as operators by enclosing their names in backticks:
566Regular functions can be used as operators by enclosing their names in backticks:
497− foo = \x -> \y -> x * y + y
569+foo = \x -> \y -> x * y + y
499− test = 10 `foo` 20
571+test = 10 `foo` 20
501Fixity declarations can associate a precedence level, which is a natural number, to a user-defined operator, and specify which way it associates:
574Fixity declarations can associate a precedence level, which is a natural number, to a user-defined operator, and specify which way it associates:
503− infixl 5 <>
577+infixl 5 <>
504− infixr 7 %%
578+infixr 7 %%
506## Foreign Function Interface
581## Foreign Function Interface
508The `extern` keyword declares a value which is defined in Javascript, and its type:
583The `extern` keyword declares a value which is defined in Javascript, and its type:
510− extern pow :: (Number, Number) -> Number
586+extern pow :: (Number, Number) -> Number
512To declare a new type with no constructors, use `extern data` and provide the kind:
589To declare a new type with no constructors, use `extern data` and provide the kind:
514− extern data IO :: * -> *
591+extern data IO :: * -> *
516− extern console :: {
593+extern console :: {
517− log :: String -> IO {}
594+ log :: String -> IO {}