Coming to PureScript from Haskell/ Reflex/ Nix
- GHCJS: Reflex
- GHCJS: Miso
I choose PureScript mostly because 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 "🍝"
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; the 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:
src/Main.hs and watch it recompile on the fly. When you are done with your changes, you would run
“So how do I use
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
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
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.