Getting Started with PureScript
Let's walk through the basics of getting set up to use the PureScript compiler
purs, and its interactive mode
We'll start with the installation of the compiler and Pulp build tool, and then go through the basic usage of
purs repl, working towards a solution of problem 1 from Project Euler.
Installing the Compiler
The Purescript compiler (
purs) can be installed with npm:
npm install -g purescript
Setting up the Development Environment
If you don't have Pulp and Bower installed, install them now:
npm install -g pulp bower
Create a new project in an empty directory using
Your directory should now contain the following files:
bower.json- contains library dependency information
bower_components/- a directory for installed dependencies
src/Main.purs- Entry point module for your project
test/Main.purs- An empty test suite
At this point, you should be able to build the project and run the tests:
pulp build pulp test
You should see output similar to the following:
* Building project in /Users/paf31/Documents/Code/purescript/pulp-test * Build successful. Running tests... You should add some tests. * Tests OK.
If everything was built successfully, and the tests ran without problems, then the last line should state "Tests OK".
Dependencies can be installed using Bower. We will be using the
purescript-lists library shortly, so install it now:
bower install purescript-lists --save
Working in PSCI
PSCi is the interactive mode of PureScript. It is useful for working with pure computations, and for testing ideas.
Open PSCi by typing
pulp repl at the command line. Pulp will create a file in your directory called
.purs-repl, which contains instructions to PSCi to load your modules and dependencies. If you invoke the PSCi executable directly, you would need to load these files by hand.
PSCi, version 0.12.0 Type :? for help import Prelude >
As the introduction indicates, you can type
:? to see a list of commands:
The following commands are available: :? Show this help menu :quit Quit PSCi :reload Reload all imported modules while discarding bindings :clear Discard all imported modules and declared bindings :browse <module> See all functions in <module> :type <expr> Show the type of <expr> :kind <type> Show the kind of <type> :show import Show all imported modules :show loaded Show all loaded modules :paste paste Enter multiple lines, terminated by ^D :complete <prefix> Show completions for <prefix> as if pressing tab Further information is available on the PureScript documentation repository: --> https://github.com/purescript/documentation/blob/master/guides/PSCi.md
We will use a selection of these commands during this tutorial.
Start by pressing the Tab key to use the autocompletion feature. You will see a collection of names of functions from the Prelude which are available to use.
To see the type of one of these values, first import the appropriate module using the
pulp init configures
.purs-repl to install
Prelude automatically, so you won't have to do it yourself.
Next, use the
:type command, followed by a space, followed by the name of the value:
> :type map forall a b f. Functor f => (a -> b) -> f a -> f b > import Data.List > :type zip forall a b. List a -> List b -> List (Tuple a b)
We will be using some of the functions from the
Data.List modules, so make sure you have imported those by using the
import Prelude import Data.List
Note that using
Tab to autocomplete names can be a useful time-saving device in
Solving Project Euler #1
The following problem is taken from Project Euler:
If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
Find the sum of all the multiples of 3 or 5 below 1000.
We can solve this problem neatly using functions and function composition, directly in the REPL.
Let's start by listing all of the natural numbers below 1000 as a list. We can do this using the
range function from
> range 0 999
You should see a list with 1000 elements printed to the command line.
This value can be given a name:
> ns = range 0 999
Now let's filter out all of those elements which do not meet the criterion. We can use the
filter function from
Data.List, by providing a predicate function as its first argument:
> multiples = filter (\n -> mod n 3 == 0 || mod n 5 == 0) ns
You can see the result by evaluating
multiples if you like, or even check its type:
> multiples (0 : 3 : 5 : 6 : ... > :type multiples List Int
Now we need to find the sum of the
multiples list, to complete the solution. We can use the
sum function from the
> import Data.Foldable > sum multiples 233168
When you have finished using PSCi, type
:quit to quit:
> :quit See ya!
Compiling a Solution
Now that we've seen how to use the REPL to reach the answer, let's move our solution into a source file and compile it.
Create a new text file
src/Euler.purs and copy the following code:
module Euler where import Prelude import Data.List (range, filter) import Data.Foldable (sum) ns = range 0 999 multiples = filter (\n -> mod n 3 == 0 || mod n 5 == 0) ns answer = sum multiples
It is possible to load this file directly into the REPL and to continue working:
pulp repl > import Euler > answer 233168 > :quit See ya!
This will compile each module present in
src/ into a separate file in the
The compiler will display several warnings about missing type declarations. In general it is considered good practice to provide explicit type signatures. In this guide, they are left out for brevity. In the absence of type signatures, the PureScript compiler infers types automatically but will remind us to consider adding them.
Writing a Test Suite
To test our code, we'll use the
bower i purescript-assert --save
test/Main.purs file, and add the following code:
module Test.Main where import Prelude import Euler (answer) import Test.Assert (assert) main = do assert (answer == 233168)
Our "test suite" is just a single assertion that the
answer value equals the correct integer. In a real test suite, we might use the
Effect monad to compose multiple tests in our
Run the tests using
pulp test, and you should hopefully see "Tests OK" in the last line.
We can modify the
main function in the
src/Main.purs module to print our result to the console:
module Main where import Prelude import Euler (answer) import Effect.Console (log) main = do log ("The answer is " <> show answer)
pulp run command can be used to compile and run the
> pulp run * Building project in pulp-test * Build successful. The answer is 233168
If you're new to typed functional programming, your next stop should be PureScript by Example, which will walk you through learning PureScript by solving practical problems. (Note: At the time of writing, Purescript by Example is compatible with the 0.11.x version of the compiler)
If you are already familiar with an ML-family language, like Haskell or Elm, PureScript by Example should still be appropriate as a starting point, but you may alternatively want to start by browsing the language reference in the documentation repository instead. The language reference gives a more brief, reference-style description of the language, and is aimed at those who are already somewhat familiar with typed functional programming. There is also a Differences from Haskell page which Haskell programmers will find useful.
New PureScript programmers are also encouraged to spend some time browsing Pursuit, which hosts generated API documentation for PureScript libraries. In particular it is worth familiarising yourself with the core libraries (i.e., those which are hosted under the
purescript organisation on GitHub), and especially the prelude, as these provide many basic concepts which are frequently useful for writing programs.