|
| 1 | +<!doctype html> |
| 2 | +<html lang="en"> |
| 3 | +<head> |
| 4 | + |
| 5 | + <meta charset="utf-8"/> |
| 6 | + <meta name="viewport" content="width=device-width, initial-scale=1"/> |
| 7 | + |
| 8 | + <title>PureScript – Articles</title> |
| 9 | + |
| 10 | + <link rel="stylesheet" href="../../css/style.css"/> |
| 11 | + <link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto:400,300,700"/> |
| 12 | + |
| 13 | +</head> |
| 14 | + |
| 15 | +<body class="download"> |
| 16 | + |
| 17 | + <header> |
| 18 | + <div class="wrap"> |
| 19 | + <h1><a href="../">PureScript</a></h1> |
| 20 | + <nav> |
| 21 | + <h2>Menu</h2> |
| 22 | + <ul> |
| 23 | + <li><a href="../../">Home</a></li> |
| 24 | + <li><a href="../../download/">Download</a></li> |
| 25 | + <li><a href="../../learn/">Learn</a></li> |
| 26 | + <li><a href="../../projects/">Projects</a></li> |
| 27 | + <li><a href="../../articles/" class="active">Articles</a></li> |
| 28 | + </ul> |
| 29 | + </nav> |
| 30 | + </div> |
| 31 | + </header> |
| 32 | + |
| 33 | + <main> |
| 34 | + |
| 35 | + <section> |
| 36 | + |
| 37 | + <h2>Getting Started with PureScript 0.7</h2> |
| 38 | + |
| 39 | + <p>Welcome to the PureScript community blog! In this first post, I'm going to walk through the basics of getting set up to use the PureScript compiler <code>psc</code>, and its interactive mode <code>psci</code>.</p> |
| 40 | + <p>I'll start with the installation of the compiler, go through the basic commands of <code>psc</code> and <code>psci</code>, working towards a solution of problem 1 from <a href="http://projecteuler.net/problem=1">Project Euler</a>.</p> |
| 41 | + <h3 id="installing-the-compiler">Installing the Compiler</h3> |
| 42 | + <p>PureScript can be installed from <a href="http://hackage.haskell.org/package/purescript">Hackage</a> or by downloading the latest <a href="https://github.com/purescript/purescript/releases">binary bundle</a> for your OS.</p> |
| 43 | + <p>Make sure the <code>psc</code> executable is on your path.</p> |
| 44 | + <h3 id="setting-up-the-development-environment">Setting up the Development Environment</h3> |
| 45 | + <p>PureScript's core libraries are configured to use the Pulp build tool, and packages are available in the Bower registry.</p> |
| 46 | + <p>If you don't have Pulp installed, install it now:</p> |
| 47 | + <pre><code>npm install -g pulp</code></pre> |
| 48 | + <p>Create a new project in an empty directory using <code>pulp init</code>:</p> |
| 49 | + <pre><code>pulp init</code></pre> |
| 50 | + <p>Your directory should now contain the following files:</p> |
| 51 | + <ul> |
| 52 | + <li><code>bower.json</code> - contains library dependency information</li> |
| 53 | + <li><code>bower_components/</code> - a directory for installed dependencies</li> |
| 54 | + <li><code>src/Main.purs</code> - Entry point module for your project</li> |
| 55 | + <li><code>test/Main.purs</code> - An empty test suite</li> |
| 56 | + </ul> |
| 57 | + <p>At this point, you should be able to build the project and run the tests:</p> |
| 58 | + <pre><code>pulp build |
| 59 | + pulp test</code></pre> |
| 60 | + <p>You should see output similar to the following:</p> |
| 61 | + <pre><code>* Building project in /Users/paf31/Documents/Code/purescript/pulp-test |
| 62 | + * Build successful. Running tests... |
| 63 | + You should add some tests. |
| 64 | + * Tests OK.</code></pre> |
| 65 | + <p>If everything was built successfully, and the tests ran without problems, then the last line should state "Tests OK".</p> |
| 66 | + <h3 id="installing-dependencies">Installing Dependencies</h3> |
| 67 | + <p>Dependencies can be installed using Bower, if you have it installed globally:</p> |
| 68 | + <pre><code>bower i purescript-lists --save</code></pre> |
| 69 | + <p>If you want to use Pulp, you can run <code>pulp dep</code>:</p> |
| 70 | + <pre><code>pulp dep i purescript-lists --save</code></pre> |
| 71 | + <h3 id="working-in-psci">Working in PSCI</h3> |
| 72 | + <p>PSCi is the interactive mode of PureScript. It is useful for working with pure computations, and for testing ideas.</p> |
| 73 | + <p>Open PSCi by typing <code>pulp psci</code> at the command line. Pulp will create a file in your directory called <code>.psci</code>, 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.</p> |
| 74 | + <pre><code> ____ ____ _ _ |
| 75 | +| _ \ _ _ _ __ ___/ ___| ___ _ __(_)_ __ | |_ |
| 76 | +| |_) | | | | '__/ _ \___ \ / __| '__| | '_ \| __| |
| 77 | +| __/| |_| | | | __/___) | (__| | | | |_) | |_ |
| 78 | +|_| \__,_|_| \___|____/ \___|_| |_| .__/ \__| |
| 79 | + |_| |
| 80 | + |
| 81 | +:? shows help |
| 82 | +></code></pre> |
| 83 | + <p>As the introduction indicates, you can type <code>:?</code> to see a list of commands:</p> |
| 84 | + <pre><code>The following commands are available: |
| 85 | + |
| 86 | +:? Show this help menu |
| 87 | +:quit Quit PSCi |
| 88 | +:reset Discard all imported modules and declared bindings |
| 89 | +:browse <module> See all functions in <module> |
| 90 | +:load <file> Load <file> for importing |
| 91 | +:foreign <file> Load foreign module <file> |
| 92 | +:type <expr> Show the type of <expr> |
| 93 | +:kind <type> Show the kind of <type> |
| 94 | +:show import Show all imported modules |
| 95 | +:show loaded Show all loaded modules |
| 96 | + |
| 97 | +Further information is available on the PureScript wiki: |
| 98 | +--> https://github.com/purescript/purescript/wiki/psci</code></pre> |
| 99 | + <p>We will use a selection of these commands during this tutorial.</p> |
| 100 | + <p>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.</p> |
| 101 | + <p>To see the type of one of these values, use the <code>:type</code> command, followed by a space, followed by the name of the value:</p> |
| 102 | + <pre><code>> :type Prelude.map |
| 103 | +forall a b f. (Prelude.Functor f) => (a -> b) -> f a -> f b |
| 104 | +> :type Data.List.zip |
| 105 | +forall a b. Data.List.List a -> Data.List.List b -> Data.List.List (Data.Tuple.Tuple a b)</code></pre> |
| 106 | + <p>We will be using some of the functions from the <code>Prelude</code> and <code>Data.List</code> modules, so import those by using the <code>import</code> keyword:</p> |
| 107 | + <pre><code>import Prelude |
| 108 | +import Data.List</code></pre> |
| 109 | + <p>Note that using <code>Tab</code> to autocomplete names can be a useful time-saving device in <code>psci</code>.</p> |
| 110 | + <h3 id="solving-project-euler-1">Solving Project Euler #1</h3> |
| 111 | + <p>The following problem is taken from <a href="http://projecteuler.net/problem=1">Project Euler</a>:</p> |
| 112 | + <blockquote> |
| 113 | + <p>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.</p> |
| 114 | + <p>Find the sum of all the multiples of 3 or 5 below 1000.</p> |
| 115 | + </blockquote> |
| 116 | + <p>We can solve this problem neatly using functions and function composition, directly in <code>psci</code>.</p> |
| 117 | + <p>Let's start by listing all of the natural numbers below 1000 as a list. We can do this using the <code>range</code> function from <code>Data.List</code>:</p> |
| 118 | + <pre><code>> range 0 999</code></pre> |
| 119 | + <p>You should see a list with 1000 elements printed to the command line.</p> |
| 120 | + <p>This value can be given a name, using a <code>let</code> binding:</p> |
| 121 | + <pre><code>> let ns = range 0 999</code></pre> |
| 122 | + <p>Now let's filter out all of those elements which do not meet the criterion. We can use the <code>filter</code> function from <code>Data.List</code>, by providing a predicate function as its first argument:</p> |
| 123 | + <pre><code>> let multiples = filter (\n -> mod n 3 == 0 || mod n 5 == 0) ns</code></pre> |
| 124 | + <p>You can see the result by evaluating <code>multiples</code> if you like, or even check its type:</p> |
| 125 | + <pre><code>> multiples |
| 126 | +Cons 0 (Cons 3 (Cons 5 (Cons 6 (Cons ... |
| 127 | +> :type multiples |
| 128 | +List Int</code></pre> |
| 129 | + <p>Now we need to find the sum of the <code>multiples</code> array, to complete the solution. We can use the <code>sum</code> function from the <code>Data.Foldable</code> module.</p> |
| 130 | + <pre><code>> import Data.Foldable |
| 131 | +> sum multiples |
| 132 | +233168</code></pre> |
| 133 | + <p>When you have finished using PSCi, type <code>:quit</code> to quit:</p> |
| 134 | + <pre><code>> :quit |
| 135 | +See ya!</code></pre> |
| 136 | + <h3 id="compiling-a-solution">Compiling a Solution</h3> |
| 137 | + <p>Now that we've seen how to use <code>psci</code> to reach the answer, let's move our solution into a source file, and compile it using <code>psc</code>.</p> |
| 138 | + <p>Create a new text file <code>src/Euler.purs</code> and copy the following code:</p> |
| 139 | + <pre class="purescript"><code>module Euler1 where |
| 140 | + |
| 141 | +import Prelude |
| 142 | + |
| 143 | +import Data.List (range, filter) |
| 144 | +import Data.Foldable (sum) |
| 145 | + |
| 146 | +ns = range 0 999 |
| 147 | + |
| 148 | +multiples = filter (\n -> mod n 3 == 0 || mod n 5 == 0) ns |
| 149 | + |
| 150 | +answer = sum multiples</code></pre> |
| 151 | + <p>It is possible to load this file directly into PSCi and to continue working:</p> |
| 152 | + <pre><code>pulp psci |
| 153 | +> Euler1.answer |
| 154 | +233168 |
| 155 | +> :quit |
| 156 | +See ya!</code></pre> |
| 157 | + <p>Alternatively, we can use Pulp to compile our new module to Javascript:</p> |
| 158 | + <pre><code>pulp build</code></pre> |
| 159 | + <p>This will compile each module present in <code>src/</code> into a separate file in the <code>output/</code> directory.</p> |
| 160 | + <h3 id="writing-a-test-suite">Writing a Test Suite</h3> |
| 161 | + <p>To test our code, we'll use the <code>purescript-assert</code> library:</p> |
| 162 | + <pre><code>bower i purescript-assert --save</code></pre> |
| 163 | + <p>Modify the <code>test/Main.purs</code> file, and add the following code:</p> |
| 164 | + <pre class="purescript"><code>module Test.Main where |
| 165 | + |
| 166 | +import Prelude |
| 167 | +import Euler1 (answer) |
| 168 | +import Test.Assert (assert) |
| 169 | + |
| 170 | +main = do |
| 171 | + assert (answer == 233168)</code></pre> |
| 172 | + <p>Our "test suite" is just a single assertion that the <code>answer</code> value equals the correct integer. In a real test suite, we might use the <code>Eff</code> monad to compose multiple tests in our <code>main</code> function.</p> |
| 173 | + <p>Run the tests using <code>pulp test</code>, and you should hopefully see "Tests OK" in the last line.</p> |
| 174 | + <h3 id="creating-executables">Creating Executables</h3> |
| 175 | + <p>We can modify the <code>main</code> function in the <code>src/Main.purs</code> module to print our result to the console:</p> |
| 176 | + <pre class="purescript"><code>module Main where |
| 177 | + |
| 178 | +import Prelude |
| 179 | +import Euler1 |
| 180 | +import Control.Monad.Eff.Console |
| 181 | + |
| 182 | +main = do |
| 183 | + log ("The answer is " ++ show answer)</code></pre> |
| 184 | + <p>The <code>pulp run</code> command can be used to compile and run the <code>Main</code> module:</p> |
| 185 | + <pre><code>> pulp run |
| 186 | +* Building project in /Users/paf31/Documents/Code/purescript/pulp-test |
| 187 | +* Build successful. |
| 188 | +The answer is 233168</code></pre> |
| 189 | + <h3 id="conclusion">Conclusion</h3> |
| 190 | + <p>That's all for this post. We've seen how to use enough of the basics of <code>psc</code> and PSCi to compile, execute and test simple PureScript programs. If you would like more information, the <a href="http://docs.purescript.org">PureScript documentation</a> lists all of the options for both <code>psc</code> and <code>psci</code>.</p> |
| 191 | + <p>Until next time...</p> |
| 192 | + |
| 193 | + </section> |
| 194 | + |
| 195 | + </main> |
| 196 | + |
| 197 | + <footer> |
| 198 | + <nav> |
| 199 | + <ul> |
| 200 | + <li><a href="../../">Home</a></li> |
| 201 | + <li><a href="../../download/" class="active">Download</a></li> |
| 202 | + <li><a href="../../learn/">Learn</a></li> |
| 203 | + <li><a href="../../projects/">Projects</a></li> |
| 204 | + <li><a href="../../articles/" class="active">Articles</a></li> |
| 205 | + </ul> |
| 206 | + <ul class="external"> |
| 207 | + <li class="github"><a href="https://github.com/purescript/purescript" title="GitHub">GitHub</a></li> |
| 208 | + <li class="twitter"><a href="https://twitter.com/purescript" title="Twitter">Twitter</a></li> |
| 209 | + </ul> |
| 210 | + </nav> |
| 211 | + </footer> |
| 212 | + |
| 213 | + <script> |
| 214 | + (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ |
| 215 | + (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), |
| 216 | + m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) |
| 217 | + })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); |
| 218 | + |
| 219 | + ga('create', 'UA-56579671-1', 'auto'); |
| 220 | + ga('send', 'pageview'); |
| 221 | + |
| 222 | + </script> |
| 223 | + |
| 224 | +</body> |
| 225 | +</html> |
0 commit comments