Skip to content

Incorporate getting-started content from book #314

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
merged 2 commits into from
May 26, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 93 additions & 6 deletions guides/Getting-Started.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,17 @@ We'll start with the installation of the compiler and Spago build tool, and then

#### Installing the Compiler

You'll need [Node.js and npm](https://docs.npmjs.com/getting-started/installing-node) and to be [able to install global packages](https://docs.npmjs.com/getting-started/fixing-npm-permissions#option-1-change-the-permission-to-npm-s-default-directory) to proceed.
You'll need to install [Node.js and npm](https://docs.npmjs.com/getting-started/installing-node). We recommend installing [Node.js and npm via a node version manager](https://docs.npmjs.com/getting-started/installing-node) to avoid issues with installing packages globally. If you choose to install it manually, you might experience the [`EACCES` error when installing packages globally](https://docs.npmjs.com/getting-started/fixing-npm-permissions#option-1-change-the-permission-to-npm-s-default-directory).

The Purescript compiler (`purs`) can be installed with npm:
Install the Purescript compiler (`purs`) with npm:

npm install -g purescript

(It can also be installed from [Hackage](http://hackage.haskell.org/package/purescript), or by downloading the latest [binary bundle](https://github.com/purescript/purescript/releases) for your OS. If you do so, make sure the `purs` executable is on your `$PATH`.)
Try running the PureScript compiler on the command line to verify that the PureScript compiler executables are available on your `$PATH`:

purs

It can also be installed from [Hackage](http://hackage.haskell.org/package/purescript), or by downloading the latest [binary bundle](https://github.com/purescript/purescript/releases) for your OS. If you do so, make sure the `purs` executable is on your `$PATH`.

#### Setting up the Development Environment

Expand All @@ -24,6 +28,8 @@ If you don't have Spago installed, install it now:

Create a new project in an empty directory using `spago init`:

mkdir my-project
cd my-project
spago init

Your directory should now contain the following files:
Expand All @@ -50,10 +56,12 @@ If everything was built successfully, and the tests ran without problems, then t

#### Installing Dependencies

Dependencies can be installed using Spago. We will be using the `purescript-lists` library shortly, so install it now:
Dependencies can be installed using Spago. We will be using the `lists` library shortly, so install it now:

spago install lists

The `lists` library sources should now be available in the `.spago/lists/{version}/` subdirectory, and will be included when you compile your project.

#### Working in PSCI

PSCi is the interactive mode of PureScript. It is useful for working with pure computations, and for testing ideas.
Expand Down Expand Up @@ -172,6 +180,11 @@ multiples = filter (\n -> mod n 3 == 0 || mod n 5 == 0) ns
answer = sum multiples
```

This sample illustrates a few key ideas regarding modules:

- Every file begins with a module header. A module name consists of one or more capitalized words separated by dots. In this case, only a single word is used, but `My.First.Module` would be an equally valid module name.
- Modules are imported using their full names, including dots to separate the parts of the module name. Here, we import the `Prelude` module, which provides `mod`, `==`, and many other common functions. We also import `Data.List` which provides the explicitly-listed `range` and `filter` functions. We can either import all functions in a module implicitly, as is done with `Prelude`, or list them explicitly. Guidelines are to only have one module with implicit imports.

It is possible to load this file directly into the REPL and to continue working:

spago repl
Expand All @@ -191,7 +204,7 @@ The compiler will display several warnings about missing type declarations. In g

#### Writing a Test Suite

To test our code, we'll use the `purescript-assert` library:
To test our code, we'll use the `assert` library:

spago install assert

Expand Down Expand Up @@ -231,10 +244,84 @@ main = do

The `spago run` command can be used to compile and run the `Main` module:

> spago run
$ spago run
[info] Build succeeded.
The answer is 233168


#### Compiling for the Browser

Spago can be used to turn our PureScript code into JavaScript suitable for use in the web browser by using the `spago bundle-app` command:

$ spago bundle-app
...
Build succeeded.
Bundle succeeded and output file to index.js

All the code in the `src` directory and any project dependencies have been compiled to JavaScript. The resulting code is bundled as `index.js` and has also had any unused code removed, a process known as dead code elimination. This `index.js` file can now be included in an HTML document. If you try this, you should see the words "Hello, World!" printed to your browser's console.

If you open `index.js`, you should see a few compiled modules which look like this:

```javascript
// Generated by purs bundle 0.13.6
var PS = {};

// ...

(function($PS) {
"use strict";
$PS["Euler"] = $PS["Euler"] || {};
var exports = $PS["Euler"];
var Data_EuclideanRing = $PS["Data.EuclideanRing"];
var Data_Foldable = $PS["Data.Foldable"];
var Data_List = $PS["Data.List"];
var Data_List_Types = $PS["Data.List.Types"];
var Data_Semiring = $PS["Data.Semiring"];
var ns = Data_List.range(0)(999);
var multiples = Data_List.filter(function (n) {
return Data_EuclideanRing.mod(Data_EuclideanRing.euclideanRingInt)(n)(3) === 0 || Data_EuclideanRing.mod(Data_EuclideanRing.euclideanRingInt)(n)(5) === 0;
})(ns);
var answer = Data_Foldable.sum(Data_List_Types.foldableList)(Data_Semiring.semiringInt)(multiples);
exports["answer"] = answer;
})(PS);

(function($PS) {
// Generated by purs version 0.13.6
"use strict";
$PS["Main"] = $PS["Main"] || {};
var exports = $PS["Main"];
var Data_Show = $PS["Data.Show"];
var Effect_Console = $PS["Effect.Console"];
var Euler = $PS["Euler"];
var main = Effect_Console.log("The answer is " + Data_Show.show(Data_Show.showInt)(Euler.answer));
exports["main"] = main;
})(PS);

PS["Main"].main();
```

This illustrates a few points about the way the PureScript compiler generates JavaScript code:

- Every module gets turned into an object, created by a wrapper function, which contains the module's exported members.
- PureScript tries to preserve the names of variables wherever possible.
- Function applications in PureScript get turned into function applications in JavaScript.
- The main method is run after all modules have been defined and is generated as a simple method call with no arguments.
- PureScript code does not rely on any runtime libraries. All of the code that is generated by the compiler originated in a PureScript module somewhere which your code depended on.

These points are important since they mean that PureScript generates simple, understandable code. The code generation process, in general, is quite a shallow transformation. It takes relatively little understanding of the language to predict what JavaScript code will be generated for a particular input.

#### Compiling CommonJS Modules

Spago can also be used to generate CommonJS modules from PureScript code. This can be useful when using NodeJS, or just when developing a larger project which uses CommonJS modules to break code into smaller components.

To build CommonJS modules, use the `spago build` command:

$ spago build
...
Build succeeded.

The generated modules will be placed in the `output` directory by default. Each PureScript module will be compiled to its own CommonJS module, in its own subdirectory.

#### What Next?

If you're new to typed functional programming, your next stop should be [PureScript by Example](https://book.purescript.org/), which will walk you through learning PureScript by solving practical problems.
Expand Down