Concepts of programming languages PureScript Christian Stuart, - - PowerPoint PPT Presentation

concepts of programming languages
SMART_READER_LITE
LIVE PREVIEW

Concepts of programming languages PureScript Christian Stuart, - - PowerPoint PPT Presentation

[Faculty of Science Information and Computing Sciences] Concepts of programming languages PureScript Christian Stuart, Douwe van Gijn, Martijn Fleuren and Nick Begg 1 [Faculty of Science Information and Computing Sciences] Presentation


slide-1
SLIDE 1

[Faculty of Science Information and Computing Sciences] 1

Concepts of programming languages

PureScript

Christian Stuart, Douwe van Gijn, Martijn Fleuren and Nick Begg

slide-2
SLIDE 2

[Faculty of Science Information and Computing Sciences] 2

Presentation overview

▶ Part 1: Introduction and Practical Matters ▶ Part 2: More Language Detail ▶ Part 3: The Foreign Function Interface ▶ Part 4: Handling side efgects

slide-3
SLIDE 3

[Faculty of Science Information and Computing Sciences] 3

Part 1 -

▶ Where Purescript fjts in the world ▶ A quick HOWTO ▶ Language introduction

slide-4
SLIDE 4

[Faculty of Science Information and Computing Sciences] 4

Where Purescript fjts in the world

▶ What is it?

The big text on the website (purescript.org): PureScript is a small strongly typed programming language that compiles to JavaScript. It is a statically typed, compiled, functional language. Someone with Haskell experience should feel at home.

slide-5
SLIDE 5

[Faculty of Science Information and Computing Sciences] 5

Where would you use it?

▶ Where you want a functional environment for

Javascript

▶ Given its JavaScript target, the common use case is for

web development - both back and front end.

▶ It happily exists inside a command line environment ▶ Has a foreign function interface, so could be used

anywhere JavaScript is used.

▶ There also exist non-Javascript backends, to varying

degrees of completion, so other bindings are possible.

slide-6
SLIDE 6

[Faculty of Science Information and Computing Sciences] 6

The language and Implementation

▶ A language and an implementation are difgerent - in

theory.

▶ Right now, there is one implementation. Along with

this, there is a lot of common best practice.

▶ (or at least, practice).

slide-7
SLIDE 7

[Faculty of Science Information and Computing Sciences] 7

Compiling

▶ The language compiles outside its runtime environment

  • ala C++, Java.

▶ The output of the compiler is Javascript. ▶ From a purely mechanical standpoint, compilation is a

string -> string conversion.

▶ That is, there is no “magic” - no private hooks into

JavaScript or Web browsers.

▶ The compiler is implemented in Haskell, but this has no

practical efgect when using it.

slide-8
SLIDE 8

[Faculty of Science Information and Computing Sciences] 8

▶ Where it fjts in the world ▶ A quick HOWTO

slide-9
SLIDE 9

[Faculty of Science Information and Computing Sciences] 9

Standard Tools - pulp

pulp is the general front-end tool for Purescript development.

▶ Generates a project environment - directory structure

and boilerplate

▶ Invokes the compiler as required (ala make) ▶ Launches your program on the cmdline ▶ Automates running test suites

slide-10
SLIDE 10

[Faculty of Science Information and Computing Sciences] 10

Standard Tools - pulp - continued

▶ Has a built in http server for running a web app -

automates starting the front- and back-end No self-respecting language these days comes without a package repository - eg CTAN / CPAN / CRAN / PyPI. Thus -

▶ Can upload your package to persuit - the Purescript

package archive.

▶ Don’t confuse it with at least one other pulp project

(package management)

slide-11
SLIDE 11

[Faculty of Science Information and Computing Sciences] 11

Standard Tools - psc, bower

▶ psc is the purescript compiler. In general, one will use

pulp to invoke this.

▶ bower is a standard package manager from the

javascript world.

▶ Module dependencies are brought into the project

using bower (bower.json)

slide-12
SLIDE 12

[Faculty of Science Information and Computing Sciences] 12

Modules

▶ Module handling not as transparent as it fjrst appears -

unlike R, Python et al

▶ Modules must be both imported into source code, and

into the project (bower.json)

slide-13
SLIDE 13

[Faculty of Science Information and Computing Sciences] 13

Hello, world!

Firstly, create a project environment with pulp - $ pulp init [verbose output removed] Now, contained in src/Main.purs: module Main where import Prelude import Control.Monad.Eff (Eff) import Control.Monad.Eff.Console (CONSOLE, log) main :: forall e. Eff (console :: CONSOLE | e) Unit main = do log "Hello sailor!"

slide-14
SLIDE 14

[Faculty of Science Information and Computing Sciences] 14

Hello, world! - Running on the commandline

$ pulp run * Building project in/Users/nick/ps-test3 Compiling Data.Show Compiling Data.Boolean Compiling Control.Semigroupoid [output trimmed] * Build successful. Hello sailor!

slide-15
SLIDE 15

[Faculty of Science Information and Computing Sciences] 15

Hello, world! - compiled as JavaScript

  • utput/Main/index.js:

// Generated by psc version 0.10.3 "use strict"; var Prelude = require("../Prelude"); var Control_Monad_Eff = require("../Control.Monad.Eff"); var Control_Monad_Eff_Console = require("../Control.Monad.Eff.Console"); var main = Control_Monad_Eff_Console.log("Hello sailor!"); module.exports = { main: main };

slide-16
SLIDE 16

[Faculty of Science Information and Computing Sciences] 16

Hello, world! - Running in a browser

Starting the backend - $ pulp server * Server listening on http://localhost:1337/ * Building project in /Users/nick/ps-test2 * Build successful. * Bundling JavaScript... * Bundled.

slide-17
SLIDE 17

[Faculty of Science Information and Computing Sciences] 17

Hello, world! - Running in a browser

Figure 1: Where did our text go?

slide-18
SLIDE 18

[Faculty of Science Information and Computing Sciences] 18

Hello, world! - Running in a browser

Where did our text go?

▶ The problem is that we printed to “stdout”; ▶ As this is a gui environment we’re not going to see

anything until we create some gui objects.

slide-19
SLIDE 19

[Faculty of Science Information and Computing Sciences] 19

Hello, world! - Running in a browser

Figure 2: There it is

slide-20
SLIDE 20

[Faculty of Science Information and Computing Sciences] 20

Interactive console mode

Fire up an interactive session ala python, ghci (with limitations!) $ pulp psci PSCi, version 0.10.3 Type :? for help > import Prelude > import Control.Monad.Eff.Console > log "hello, nautical professional!" hello, nautical professional! unit > 7+5 12

slide-21
SLIDE 21

[Faculty of Science Information and Computing Sciences] 21

▶ Where it fjts in the world ▶ A quick HOWTO ▶ Language introduction

slide-22
SLIDE 22

[Faculty of Science Information and Computing Sciences] 22

Language Overview - Basic Types

▶ JavaScript Basic types: Number, String, Boolean ▶ Additional Native types: integers, characters, arrays,

records, and functions

slide-23
SLIDE 23

[Faculty of Science Information and Computing Sciences] 23

Basic Types - Numbers

> :type 1 Int > :type 1.7 Number

slide-24
SLIDE 24

[Faculty of Science Information and Computing Sciences] 24

Basic Types - Boolean

> :type true Boolean > :type false Boolean

slide-25
SLIDE 25

[Faculty of Science Information and Computing Sciences] 25

Basic Types - Strings

> :type "boat" String :type 'b' Char

slide-26
SLIDE 26

[Faculty of Science Information and Computing Sciences] 26

Basic Types - Strictness

▶ :: gives a type signature

> true :: Boolean true

slide-27
SLIDE 27

[Faculty of Science Information and Computing Sciences] 27

Basic Types - Strictness

▶ Predictably -

> 7 :: Boolean Error found: in module $PSCI at line 1, column 1 - line 1, column 3 Could not match type Int with type Boolean while checking that type Int is at least as general as type Boolean while checking that expression 7has type Boolean in value declaration it

slide-28
SLIDE 28

[Faculty of Science Information and Computing Sciences] 28

Basic Types - Strictness

> true :: Int Error found: in module $PSCI at line 1, column 1 - line 1, column 5 Could not match type Boolean with type Int while checking that type Boolean is at least as general as type Int while checking that expression true has type Int in value declaration it

slide-29
SLIDE 29

[Faculty of Science Information and Computing Sciences] 29

Language Overview - Arrays

> [1,1,2,3,5,8] :: Array Int [1,1,2,3,5,8] > [1,1,2,3,5,8] [1,1,2,3,5,8] > :type [1,1,2,3,5,8] Array Int

slide-30
SLIDE 30

[Faculty of Science Information and Computing Sciences] 30

Language Overview - Arrays

Arrays must be homogeneous > [1, 2, 2.5] Error found: in module $PSCI at line 1, column 1 - line 1, column 11 Could not match type Int with type Number

slide-31
SLIDE 31

[Faculty of Science Information and Computing Sciences] 31

Language Overview - Function

module Main where import Prelude import Control.Monad.Eff.Console (log, logShow) fibonacci :: Int -> Int fibonacci 0 = 0 fibonacci 1 = 1 fibonacci n = fibonacci (n - 2) + fibonacci (n - 1) main = do logShow (fibonacci 7) logShow (fibonacci 15)

slide-32
SLIDE 32

[Faculty of Science Information and Computing Sciences] 32

Function - compiled

var fibonacci = function (v) { if (v === 0) { return 0; }; if (v === 1) { return 1; }; return fibonacci(v - 2) + fibonacci(v - 1) | 0; }; var main = function __do() { Control_Monad_Eff_Console.logShow (Data_Show.showInt)(fibonacci(7))(); return Control_Monad_Eff_Console.logShow (Data_Show.showInt)(fibonacci(15))(); };

slide-33
SLIDE 33

[Faculty of Science Information and Computing Sciences] 33

Function - running

$ pulp run * Building project in/Users/nick/ps/interactive Compiling Main [much output removed] * Build successful. 13 610

slide-34
SLIDE 34

[Faculty of Science Information and Computing Sciences] 34

Features

▶ It has no runtime overhead ▶ Type security using javascript features ▶ Type classes ▶ Extensible records ▶ Human readable and debuggable output ▶ Many more such as: ADT’s, pattern matching, type

inference, rank-N types, etc.

slide-35
SLIDE 35

[Faculty of Science Information and Computing Sciences] 35

Some examples

▶ It has no runtime ▶ Type security using javascript features ▶ Type classes ▶ Extensible records ▶ Human readable and debuggable output ▶ Many more such as: ADT’s, pattern matching, type

inference, rank-N types, etc. I am going to talk about the bold faced topics.

slide-36
SLIDE 36

[Faculty of Science Information and Computing Sciences] 36

Type security

Javascript actually only has one type, but they can be roughly classifjed value type "" string []

  • bject

{}

  • bject

null

  • bject

undefined undefined 1 number true boolean (function(){}) function Purescript has taken some measures to make sure that the generated code behaves well.

slide-37
SLIDE 37

[Faculty of Science Information and Computing Sciences] 37

Type security

So this does not happen > [] + {} '[object Object]' > {} + [] WAT

slide-38
SLIDE 38

[Faculty of Science Information and Computing Sciences] 37

Type security

So this does not happen > [] + {} '[object Object]' > {} + [] WAT

slide-39
SLIDE 39

[Faculty of Science Information and Computing Sciences] 38

Type security

for example, this defjnition x :: Int x = 5 will be var x = 5 | 0; in compiled purescript. Why?

slide-40
SLIDE 40

[Faculty of Science Information and Computing Sciences] 39

Type classes

They are very similar to Haskells, except that dependent type classes are defjned with class (Eq a) <= Ord a where ... Note that the arrow is inverted. This was a subtle design choice for the purescript developers.

slide-41
SLIDE 41

[Faculty of Science Information and Computing Sciences] 40

Type classes

When defjning instances they have to be named instance showVector :: Show Vector where show = showV showV :: forall a. Show a => Vector a -> String showV (Vector {x: x, y: y}) = "[" <> show x <> "; " <> show y <> "]" Things to note: Explicit forall, concatenation operator, pattern matching on records,

slide-42
SLIDE 42

[Faculty of Science Information and Computing Sciences] 41

Extensible records

Sticking to the records from before, and we have a data type data Vector = Vector { x :: Double, y :: Double} then, in purescript syntax type Vector = { x :: Number, y :: Number } -- Not even a constructor will introduce a Vector constructor in PureScript that accepts an object type. It is fjlled in for you.

slide-43
SLIDE 43

[Faculty of Science Information and Computing Sciences] 42

Extensible records

So we can do this

  • rigin :: Vector
  • rigin = {x: 0, y: 0 } -- JSON syntax setters
  • r this
  • riginX :: Number
  • riginX = origin.x -- Object field getters

If you pattern match on a constructor then you have to do it with JSON Syntax

slide-44
SLIDE 44

[Faculty of Science Information and Computing Sciences] 43

Extensible records

Update syntax is similar to Haskells setX :: Number -> Vector -> Vector setX val point = point { x = val }

  • - the same as

setX val (Vector {x: x, y: y}) = Vector {x: val, y: y}

  • - if Vector would have a constructor
slide-45
SLIDE 45

[Faculty of Science Information and Computing Sciences] 44

Difgerences with Haskell

Purescript is heavily infmuenced by Haskell, so what are the difgerences? Inverted type class arrow Explicit efgects in the Eff Monad main :: forall e . Eff (fs :: FS, trace :: Trace, process :: Process | e) Unit Explicit forall No syntactic sugar for lists Type class instances are named

slide-46
SLIDE 46

[Faculty of Science Information and Computing Sciences] 44

Difgerences with Haskell

Purescript is heavily infmuenced by Haskell, so what are the difgerences?

▶ Inverted type class arrow ▶ Explicit efgects in the Eff Monad

main :: forall e . Eff (fs :: FS, trace :: Trace, process :: Process | e) Unit

▶ Explicit forall ▶ No syntactic sugar for lists ▶ Type class instances are named

slide-47
SLIDE 47

[Faculty of Science Information and Computing Sciences] 45

What does that compile to?

Let’s look at a few examples:

▶ Currying ▶ Algebraic data types ▶ Type class instance

slide-48
SLIDE 48

[Faculty of Science Information and Computing Sciences] 46

Currying

Remember the input: add x y = x + y add = function (x) { return function(y) { return (x + y | 0); } } Not a lot of trickery going on here.

slide-49
SLIDE 49

[Faculty of Science Information and Computing Sciences] 47

Algebraic data types

Let’s look at ADT’s. First we look at the Nothing constructor, remember the input: data Maybe a = Nothing | Just a Nothing will then be var Nothing = (function () { function Nothing() { }; Nothing.value = new Nothing(); return Nothing; })(); What is going on here?

slide-50
SLIDE 50

[Faculty of Science Information and Computing Sciences] 47

Algebraic data types

Let’s look at ADT’s. First we look at the Nothing constructor, remember the input: data Maybe a = Nothing | Just a Nothing will then be var Nothing = (function () { function Nothing() { }; Nothing.value = new Nothing(); return Nothing; })(); What is going on here?

slide-51
SLIDE 51

[Faculty of Science Information and Computing Sciences] 48

Algebraic data types

▶ As it turns out, this is a lexical closure. ▶ Protects the function body from global variable

defjnition ‘pollution’.

slide-52
SLIDE 52

[Faculty of Science Information and Computing Sciences] 49

Algebraic data types

input data Maybe a = Nothing | Just a Let’s see if we can dissect this function with the knowledge from the previous slide. var Just = (function () { function Just(value0) { this.value0 = value0; }; Just.create = function(value0) { return new Just(value0); }; return Just; })();

slide-53
SLIDE 53

[Faculty of Science Information and Computing Sciences] 50

Type class instance

Assume that we want to have a nice Vector representation in this way psci> Vector 2 3 [2; 3] data Vector = Vector { x :: Number, y :: Number } instance showVector :: Show Vector where show vec = "[" <> show vec.x <> "; " show vec.y <> "]"

slide-54
SLIDE 54

[Faculty of Science Information and Computing Sciences] 51

Type class instance

var showVector = new Data_Show.Show(function (v) { return "[" + (Data_Show.show(Data_Show.showNumber)(v.x) + ("; " + (Data_Show.show(Data_Show.showNumber)(v.y) + "]"))); // String is constructed from right to left It is immediately clear why they have chosen for named instances.

slide-55
SLIDE 55

[Faculty of Science Information and Computing Sciences] 52

The Foreign Function Interface

▶ Built to interface with JavaScript ▶ Native JavaScript support ▶ Compiles to user-friendly JavaScript

slide-56
SLIDE 56

[Faculty of Science Information and Computing Sciences] 53

Calling PureScript from JavaScript

mul :: Int -> Int -> Int mul x y = x * y Compiles to: var mul = function (x) { return function (y) { return x * y | 0; }; }; Result: > mul(3)(2); 6

slide-57
SLIDE 57

[Faculty of Science Information and Computing Sciences] 54

Calling JavaScript from PureScript

To use foreign functions in a PureScript module we need to:

▶ add a JavaScript module with the same name as the

module

▶ expose the foreign function via that module ▶ declare the type of the JavaScript function object

slide-58
SLIDE 58

[Faculty of Science Information and Computing Sciences] 55

Example: Math bindings

▶ Math.purs, the PureScript module in which the types

are declared

▶ Math.js, the JavaScript module in which the functions

are defjned The compiler will combine these into one module.

slide-59
SLIDE 59

[Faculty of Science Information and Computing Sciences] 56

Math.purs

The PureScript module fjle contains the type declaration: foreign import exp :: Number -> Number

slide-60
SLIDE 60

[Faculty of Science Information and Computing Sciences] 57

Math.js

The JavaScript fjle belongs to the PureScript module, and contains the function defjnition: exports.exp = function (x) { return Math.exp(x); };

slide-61
SLIDE 61

[Faculty of Science Information and Computing Sciences] 58

Calling the function:

> import Math (exp) > exp 1 2.718

slide-62
SLIDE 62

[Faculty of Science Information and Computing Sciences] 59

Type safety

Lets change our function: exports.exp = function (x) { return "Hello World!"; }; What happens now?

slide-63
SLIDE 63

[Faculty of Science Information and Computing Sciences] 60

Running the function: > import Math (exp) > exp 1 "Hello World!" Foreign functions are not type safe! The declared type is only a label.

slide-64
SLIDE 64

[Faculty of Science Information and Computing Sciences] 61

Multiple arguments

foreign import pow :: Number -> Number -> Number exports.pow = function(x, y){ return Math.pow(x, y); } What’s wrong here?

slide-65
SLIDE 65

[Faculty of Science Information and Computing Sciences] 62

Javascript: > pow(3) NaN pow is not curried!

slide-66
SLIDE 66

[Faculty of Science Information and Computing Sciences] 63

Type Safety

JavaScript functions are not type safe PureScript provides the Foreign module

slide-67
SLIDE 67

[Faculty of Science Information and Computing Sciences] 64

The module gives us:

▶ Foreign: a type that can be any valid JavaScript value ▶ An F monad, which is a special case of the Except

monad.

▶ functions

▶ readInt :: Foreign -> F Int, ▶ readNumber :: Foreign -> F Number, ▶ readProp :: String -> Foreign -> F Foreign ▶ etc.

slide-68
SLIDE 68

[Faculty of Science Information and Computing Sciences] 65

type F a = Except (NonEmptyList ForeignError) a Analogous to Haskell’s Except monad runExcept: Except e a -> Either e a

slide-69
SLIDE 69

[Faculty of Science Information and Computing Sciences] 66

Provided by PureScript: readInt :: Foreign -> F Int Our new halve import: foreign import halve :: Int -> Foreign

slide-70
SLIDE 70

[Faculty of Science Information and Computing Sciences] 67

> runExcept $ (readInt <<< halve) 4 (Right 2) > runExcept $ (readInt <<< halve) 3 (Left (NonEmptyList (NonEmpty (TypeMismatch "Int" "Number") Nil)))

slide-71
SLIDE 71

[Faculty of Science Information and Computing Sciences] 68

Currying and uncurrying

PureScript ofgers:

▶ Fn0, Fn1, Fn2 … Fn10: Datatypes representing an

uncurried function with N arguments.

▶ runFn1, runFn2 … : Curry functions. ▶ mkFn1, mkFn2 … : Uncurry functions.

slide-72
SLIDE 72

[Faculty of Science Information and Computing Sciences] 69

import Data.Function.Uncurried (Fn2, runFn2) foreign import pow :: Fn2 Number Number Number pow' -> Number Number Number pow' = runFn2 pow runFn2 curries the function: runFn2 :: Fn2 a b c -> a -> b -> c

slide-73
SLIDE 73

[Faculty of Science Information and Computing Sciences] 70

import Data.Function.Uncurried (Fn2, mkFn2) add :: Fn Number Number Number add = mkFn2 add' where add' x y = x + y mkFn2 uncurries the function: mkFn2 :: (a -> b -> c) -> Fn2 a b c

slide-74
SLIDE 74

[Faculty of Science Information and Computing Sciences] 71

What about side efgects? Functions with side efgects need to be declared as Eff monads, with an appropriate efgect type. For example, Console.log is declared as: foreign import log :: forall eff . String

  • > Eff (console :: CONSOLE | eff) Unit
slide-75
SLIDE 75

[Faculty of Science Information and Computing Sciences] 72

part 4: Handling side efgects

Figure 3: Obligatory XKCD

slide-76
SLIDE 76

[Faculty of Science Information and Computing Sciences] 73

Eff monad

▶ Side efgects are handled in with the Eff monad. ▶ More granular than Haskell’s IO monad.

slide-77
SLIDE 77

[Faculty of Science Information and Computing Sciences] 74

side efgects in Haskell

main :: IO () Meaning: main has side-efgects.

slide-78
SLIDE 78

[Faculty of Science Information and Computing Sciences] 75

side efgects in PureScript

main :: Eff (fs :: FS, trace :: Trace, process :: Process) Unit Meaning: The main function…

▶ uses the fjle system ▶ can trace out to the console ▶ does something to the current process

slide-79
SLIDE 79

[Faculty of Science Information and Computing Sciences] 76

granularity makes sense

JavaScript was designed for interactivity in the browser. Typical PureScript program has more I/O than typical Haskell program.

slide-80
SLIDE 80

[Faculty of Science Information and Computing Sciences] 77

there are a lot of efgects

Examples of general purpose efgects:

▶ Console IO ▶ Random number generation ▶ Exceptions ▶ Reading/writing mutable state ▶ …

Examples of browser efgects:

▶ DOM manipulation ▶ AJAX calls ▶ talking to a websocket ▶ reading/writing in local storage ▶ …

slide-81
SLIDE 81

[Faculty of Science Information and Computing Sciences] 78

example: printing a random number

module Main where import Prelude import Control.Monad.Eff import Control.Monad.Eff.Random import Control.Monad.Eff.Console main :: Eff (console :: CONSOLE, random :: RANDOM) Unit main = do n <- random logShow n

▶ returned 0.5547845012090082 for me

slide-82
SLIDE 82

[Faculty of Science Information and Computing Sciences] 79

Eff is magic (and fast!)

The compiler knows about the Eff monad. Optimizes away calls to >>= (bind) I/O is as fast as JavaScript

slide-83
SLIDE 83

[Faculty of Science Information and Computing Sciences] 80

var main = Prelude[">>="] (Control_Monad_Eff.monadEff()) (Control_Monad_Eff_Random.random) (function (n) { return Control_Monad_Eff_Console.logShow( Prelude.showNumber())(n); });

slide-84
SLIDE 84

[Faculty of Science Information and Computing Sciences] 81

var main = function __do() { var n = Control_Monad_Eff_Random.random(); return Control_Monad_Eff_Console.logShow( Prelude.showNumber())(n)(); };

slide-85
SLIDE 85

[Faculty of Science Information and Computing Sciences] 82

Defjne your own efgect

You can import JavaScript code as an efgect. Let’s implement a counter!

slide-86
SLIDE 86

[Faculty of Science Information and Computing Sciences] 83

Example: counter

PureScript code: foreign import data COUNTER :: ! foreign import incrCounter :: Eff ( counter :: COUNTER) Number

slide-87
SLIDE 87

[Faculty of Science Information and Computing Sciences] 84

JavaScript code: exports.incrCounter = function() { return ++globalCounter; };

slide-88
SLIDE 88

[Faculty of Science Information and Computing Sciences] 85

main :: Eff (console :: CONSOLE, counter :: COUNTER) Unit main = do a <- incrCounter b <- incrCounter c <- incrCounter logShow a logShow b logShow c

▶ returns 1 2 3

slide-89
SLIDE 89

[Faculty of Science Information and Computing Sciences] 86

Conclusion

Great alternative to JavaScript. In relation to Haskell:

▶ generally more precise ▶ generally more verbose ▶ generally more orthogonal

slide-90
SLIDE 90

[Faculty of Science Information and Computing Sciences] 87

External Links

▶ Language Website

http://www.purescript.org

▶ Getting started

http://www.purescript.org/learn/getting-started

▶ Purescript by Example

https://leanpub.com/purescript/read

▶ Try Purescript

http://try.purescript.org

▶ Try Thermite

http://try.purescript.org/?backend=thermite

▶ Browserify

http://browserify.org