Skip to content
Kotlin-backend for PureScript
Haskell Dhall PureScript Dockerfile Nix Kotlin Makefile
Branch: kotlin
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.
app use shake for build for caching Sep 14, 2019
src more inlining Sep 15, 2019
test more inlining Sep 15, 2019
.gitignore update ci for sym linking Sep 14, 2019
.gitlab-ci.yml Change executable name to pscpp Aug 9, 2018
Dockerfile update todos Sep 15, 2019
LICENSE Clean up header comments Aug 9, 2018
Makefile use shake for build for caching Sep 14, 2019 more inlining Sep 15, 2019
Setup.hs New baseline based on dump-corefn output Jul 29, 2018
package.yaml use shake for build for caching Sep 14, 2019
pskt.cabal update ci for sym linking Sep 14, 2019
stack.nix adding support for building using nix Apr 4, 2019
stack.yaml recursive definitions finally working Sep 3, 2019
stack.yaml.lock update ci for sym linking Sep 14, 2019


Kotlin-Backend for PureScript. PsKt is forked from purescript-native

pipeline status


The goal of this project is to support native android development in PureScript using Kotlin. Kotlin was chosen, because it has first-class support from Android. This means, that the complete API is available through the FFI.


The Linux executable can be downloaded here

$ git clone ....
$ make
$ make install
# pskt should no be available in your PATH
$ pskt

Project Setup

$ cd your-project

# setup purescript
$ mkdir purescript
$ cd purescript
$ spago init
$ spago build -- -g corefn && pskt
# transpiled files will be written to output/pskt
# import foreign files for kotlin
$ git clone ../src/main/kotlin/foreigns
# symlink generated files
$ ln -s output/pskt ../src/main/kotlin/generated


When compiling with kotlinc you might get some weird errors like OutOfMemory exceptions. This can be fixed by using a gradle build script. See kotlin test for an example.

Sometimes the kotlin compiler reports this error: e: ...Main.kt: (6, 8): Redeclaration: Module The fix is removing the gradle build folder and compiling again: rm -r build


PureScript Kotlin
Int Int (might be changed to Long)
Number Double
Array List
String String
Char Char
Boolean Boolean
Records Map<String, Any>
Unit Unit

Data types are faithfully represented using sealed classes:

data T a = T a | B Int String


sealed class _Type_T() {
  data class T(val value0: Any)
  data class B(val value0: Any, val value1: Any)

Function calls are sugared with .app(...) to make the generated code more readable. app is an extension function, that can be inlined by the kotlin compiler adding to runtime overhead.


  • All transpiled Purescript modules will be located in the PS. package in Kotlin (eg. Data.Array in PS will be PS.Data.Array in Kt)
  • Definitions in a module in Purescript will be located in the Module object (eg. Data.Array.range in PS will be PS.Data.Array.Module.range in Kt)
  • Foreign definitions are located in the Foreign. package in Kotlin, followed by the same Namespace that is used in Purescript (eg. the foreign definition arrayMapImpl in the module Data.Array should be located in Foreign.Data.Array in Kotlin)


To run a purescript program main :: Effect Unit:

fun main() {
  PS.MyModule.main() // or use .appRun() if the type is Any


Implementations for FFI files for prelude and some default libraries can be found here. The implementation is not complete but mostly working.

FFIs should be implemented using lambda expressions (not anonymous functions) and accept Any as the arguments:

package Foreign.Data.MyFFI;

val myFFI = { str: Any ->
  { f: Any ->
    str as String; f as (String -> (Int -> Double))


The actual types can be added using casts in the body. Kotlin will smart-cast the arguments (here str and f) to their respective type.

Effect a is represented as () -> Any; just like PureScript represents it in JavaScript.

Note, that names are normalized: _ is replaced by __ and $ is replaced by _dollar. For example if you define a foreign import named _myFFI in purescript, the corresponding definition in kotlin must be named __myFFI.


An example for android can be found here.


You can’t perform that action at this time.