A small strongly typed language that compiles to Javascript^W Erlang
Haskell PureScript CSS Shell JavaScript Makefile
Pull request Compare This branch is 65 commits ahead, 1 commit behind purescript:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.
app Initial working version with 0.12 merged, some opts disabled Jun 3, 2018
appveyor Add a mechanism for invalidating that AppVeyor cache May 14, 2016
bundle Update INSTALL.md and bundle/README for 0.12 (#3357) May 8, 2018
core-tests Move solved type classes into Prim modules & bump test deps (#3312) Apr 24, 2018
license-generator Include git commit information in non-release builds (#2669) Feb 20, 2017
psc-ide [purs ide] Removes Pursuit commands (#3355) May 8, 2018
src Erl restore magic-do/inlining opts Jul 16, 2018
tests Bump to 0.12.0 (#3365) May 21, 2018
travis Rename prim classes (#3176) Mar 25, 2018
.gitignore Examples is a silly name for tests (#3328) Apr 27, 2018
.travis.yml Also build erl branch (why isn't it master?) Jul 19, 2018
CONTRIBUTING.md Examples is a silly name for tests (#3328) Apr 27, 2018
CONTRIBUTORS.md Add myself to Contributors (#3346) May 2, 2018
INSTALL.md Update INSTALL.md and bundle/README for 0.12 (#3357) May 8, 2018
LICENSE Update LICENSE (#2674) Feb 18, 2017
Makefile Add a Makefile with ghcid and testing commands (#3290) Apr 11, 2018
README.md Fix bogus references to pserlc Dec 21, 2017
Setup.hs Fix #624 - remove xdg-basedir dependency, simplify build. Oct 15, 2014
appveyor.yml update stack resolver to lts-10.3 (#3209) Jan 21, 2018
logo.png Revise readme Mar 20, 2015
make_release_notes Add release notes script Dec 16, 2015
package.yaml Bump to 0.12.0 (#3365) May 21, 2018
stack.yaml [purs ide] Removes Pursuit commands (#3355) May 8, 2018


PureScript - Erlang backend

A small strongly typed programming language with expressive types that compiles to JavaScript, written in and inspired by Haskell.

This fork is a PureScript backend targetting Erlang source. The purerl organisation hosts ports of some core libraries.

To use it, it is recommended to use psc-package and the purerl package sets. In a psc-package project, compile with something like

psc-package sources | xargs purs 'src/**/*.purs'

or if using bower:

purs 'bower_components/purescript-*/src/**/*.purs' 'src/**/*.purs'

Then build and run the Erlang output:

erlc -o ebin/ output/*/*.erl
erl -pa ebin -noshell -eval '(main@ps:main@c())()' -eval 'init:stop()'

See hello-world example.

Erlang/OTP 19 supported, subtle & catastrophic bugs have been observed with earlier versions. If you do try with an earlier version minimum 17 is suggested due to character encoding.


Module names Foo.Bar are transformed to a lower-snake cased form foo_bar (any non-initial uppercase chars will be preserved as such), with a suffix @ps to avoid clashing with built-in erlang modules.

Top level declarations are uniformly output as nullary functions. Identifiers are preserved, with quoting if required. Thus a normal invocation of the output will look like (main@ps:main())().


PureScript type Erlang type Notes
Int integer() Arbitrary precision - no longer a Bounded
Number float()
Boolean boolean()
String string() Should consider binary() representation
Array array() Not to be confused with erlang [] list syntax.
Records #{atom() => any()} Map keyed by atoms
Tagged union Tuple with tag element e.g. Some 42 is {some, 42}
Newtype as underlying type
Functions Function (arity 1 - but see FFI)
Data.Function.Uncurried.FnX Function (arity X) Actual higher arity functions - for 'uncurried' functions from tuples see Erl.Data.Tuple
Erl.Data.List list() Native lists via purescript-erl-lists
Erl.Data.Tuple tuple() Native tuples via purescript-erl-tuples


In place of .js FFI files, the Erlang backend has .erl FFI files. As per the regular compiler since 0.9, these must be placed along the corresponding .purs file with the same name.

Module name: Foo.MyModule PureScript file Foo/MyModule.purs Erlang file: Foo/MyModule.erl Erlang module: foo_myModule@foreign

Note that the FFI code for a module must not only be in a file named correctly, but the module must be named the same as the output module with @foreign appended.

FFI files MUST export explicitly the exact set of identifiers which will be imported by the corresponding PureScript file. The compiler will check these exports and use them to inform codegen.

Auto-currying: functions can be defined with any arity. According to the arity of the export (parsed from the export list) the compiler will automatically apply to the right number of arguments. By extension, values are exported as a function of arity 0 returning that value.

An example:

module Foo.Bar where

foreign import f :: Int -> Int -> Int -> Int

f(X, Y, Z) -> X + Y * Z.

This could also have been defined as


f(X) ->
  fun (Y) ->
    fun (Z) ->
      X + Y * Z