EDIT (Mar, 2023): Checkout https://github.com/purifix/purifix if you want to Nixify your PureScript projects.
My Haskell app Neuron recently received a contribution that added support for the very useful client-side search feature. JavaScript was used to implement it; however after having gotten used to merrily creating Reflex-FRP-based web apps (frontend and backend both in Haskell), writing raw JavaScript had very little appeal to me, which left me with the following options:
- GHCJS: Reflex
- GHCJS: Miso
- PureScript
One appeal of PureScript is that it is comparitively lightweight to install, develop and use (which is how Iβd describe neuron itself).
Creating a Hello World project
If you already use Nix (or NixOS), getting a quick feel for PureScript is just a matter of running:
nix-shell -p purescript -p spago
Spago is the PureScript package manager. It uses Dhall for configuration, which is exactly what Neuron uses as well. Once you are in the nix-shell we shall create a new PureScript project:
mkdir /tmp/app1 && cd /tmp/app1
spago init
The project will have minimal files:
$ tree
.
βββ packages.dhall
βββ spago.dhall
βββ src
βΒ Β βββ Main.purs
βββ test
βββ Main.purs
2 directories, 4 files
and very basic PureScript code:
-- src/Main.purs
module Main where
import Prelude
import Effect (Effect)
import Effect.Console (log)
main :: Effect Unit
main = do
log "π"
To build the final JavaScript βexecutableβ, run spago bundle-app
; it will generate a index.js
for use from HTML.
$ spago bundle-app
[info] Installation complete.
[info] Build succeeded.
[info] Bundle succeeded and output file to index.js
$ wc -l -c index.js
29 792 index.js
Thatβs basically it. Very easy to install and use!
ghcid of PureScript
Not using any fancy IDE, I find ghcid to be critical to my Haskell development workflow; its fast compile-reload cycle facilitates a very delightful development experience. I wanted to have this with PureScript. Fortunately, such a tool exists β pscid. pscid is available in Nix, so you may simply restart that nix-shell as:
nix-shell -p purescript -p spago -p pscid
Then visit the project directory, and run:
pscid
Now modify src/Main.hs
and watch it recompile on the fly. When you are done with your changes, you would run spago bundle-app
at the end to build the final JavaScript.
βSo how do I use getElementById
?β
Haskellers are familiar with Hoogle. In PureScript ecosystem, that is called Pursuit. I wanted to know, as part of adding PureScript to neuron, how to use the famous getElementById
function in PureScript; and pursuit came to help.
getElementById :: String -> NonElementParentNode -> Effect (Maybe Element)
Hmm, what is βNonElementParentNode
β? This function is from the purescript-web-dom
library, which uses the DOM spec which does indeed document this second argument, although it is implicitly provided by this
in JavaScript. In PureScript you would pass it explicitly. HTML Document is one of the values it can take:
main = do
doc <- map toNonElementParentNode $ document =<< window
myElem <- getElementById "someId" doc
EDIT: The lack of documentation around things like this is something I noticed immediately in the PureScript ecosystem; a lobste.rs user explains it here.
Logging to console
The project template already uses the log
function to log strings to browser console. But how do we log an arbitrary PureScript object, like the DOM element? Using traceM
:
import Debug.Trace (traceM)
main = do
doc <- map toNonElementParentNode $ document =<< window
myElem <- getElementById "someId" doc
traceM myElem
And thatβs all it takes to get the initial feel for what it is like to develop PureScript as a Haskeller who comes from the world of Nix and GHCJS.
External links
- Getting Started with PureScript (official guide)