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
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.