Purescript is a language that borrows many ideas from Haskell, but compiles down to Javascript. In sum, Purescript gives you:
Here’s a sample:
module Main where
import Debug.Trace
data RPS = R | P | S
-- defining equality for the RPS data type
instance eqRPS :: Eq RPS where
(==) R R = true
(==) P P = true
(==) S S = true
(==) _ _ = false
(/=) l r = not (l == r)
factorial :: Number -> Number
factorial 0 = 1
factorial n = n * factorial (n - 1)
-- iterative application of a function f
iterate :: forall a. (a -> a) -> Number -> a -> a
iterate _ 0 x = x
iterate f n x = iterate f (n - 1) (f x)
main = trace $ show $ iterate (\x -> x+1) 10 1
I highly recommend Phil Freeman’s freely available purescript book, as well as the docs for more details on the language itself.
Before I dive into the details of my purescript + emacs setup, I’d like to share some background.
I’ve worked with emacs for a long time. Part of my evaluating a new (to me) programming language is determining how much emacs can do for me.
I’ve been a Haskeller for just over a year now. When I realized how much of the effort of programming Haskell I could push into emacs, I was blown away.
Thanks to ghc-mod, I’m able to (without leaving my emacs buffer):
I cannot over-emphasize how powerful this setup is. Every time I save, it is as if a unit test suite has been run over my entire project, only, even more powerful than that thanks to Curry-Howard. Not only that, but I don’t have to interrupt my editing flow to do so.
Here’s a few screenshots of this in action:
I only use a subset of the full power of emacs for Haskell development, and already I reap enormous benefits. For setting up emacs and Haskell, I recommend Alejandro Serrano’s post.
I’ve arrived at Purescript and I’m ready to develop! In order to get the most of my editor, I went looking around for tools to help emacs understand purescript. Here’s what I found:
Follow the instructions for installing each of the above. Note that installing purscheck requires a working Haskell installation.
Here’s the relevant bits of my init.el
with comments in-line:
;; flycheck - automated checker module for emacs
;; import the flycheck symbols
(require 'flycheck)
;; connect purscheck to emacs, parsing errors and warnings
(flycheck-define-checker purs-check
"Use purscheck to flycheck PureScript code."
:command ("purscheck" source source-original temporary-file-name)
:error-patterns
((error line-start
(or (and "Error at " (file-name) " line " line ", column " column ":" (zero-or-more " "))
(and "\"" (file-name) "\" (line " line ", column " column "):"))
(or (message (one-or-more not-newline))
(and "\n"
(message
(zero-or-more " ") (one-or-more not-newline)
(zero-or-more "\n"
(zero-or-more " ")
(one-or-more not-newline)))))
line-end))
:modes purescript-mode)
;; connect flycheck with purscheck
(add-to-list 'flycheck-checkers 'purs-check)
;; add the purescript-mode directory to emacs necessary because
;; purescript isn't on melpa/marmalde at the moment
(add-to-list 'load-path "~/development/purescript-mode/")
;; enable purescript smart indentation and purscheck whenever a
;; purescript file is loaded into emacs
(require 'purescript-mode-autoloads)
(add-hook 'purescript-mode-hook 'turn-on-purescript-indentation)
(add-hook 'purescript-mode-hook 'flycheck-mode)
With the setup above, I get:
I’m missing the following in purescript:
I’ve yet to work with elisp, but I suspect one of the quickest paths to get these kinds of features is to start-up purescript interpret mode (psci) in the background, and have emacs communicate with it to parse out the results of :k (expression kind), :i (expression information), and :t (expression type).
All in all, though, I’m very pleased with the purescript editing ecosystem. It’s enough to go far as it is.