.circleci | ||
.devcontainer | ||
.github | ||
asterius | ||
docs | ||
ghc-toolkit | ||
npm-utils | ||
utils | ||
wasm-toolkit | ||
.dockerignore | ||
.envrc | ||
.ghcid | ||
.gitignore | ||
base.Dockerfile | ||
dev.Dockerfile | ||
lts.sh | ||
README.md | ||
stack-profile.yaml | ||
stack.yaml | ||
stackage.Dockerfile |
Asterius: A Haskell to WebAssembly compiler
Asterius is a Haskell to WebAssembly compiler based on GHC. It compiles simple
Haskell source files or Cabal executable targets to WebAssembly+JavaScript code
which can be run in node.js or browsers. It features seamless JavaScript interop
(lightweight Async FFI with Promise
support) and small output code (~600KB
hello.wasm
for a Hello
World). A lot of common
Haskell packages like lens
are already supported. The project is actively
maintained by Tweag I/O.
Precompiled examples
Here are the precompiled web versions of some popular Haskell apps; feel free to give it a try in your browser!
Quickstart using the pre-built Docker image
We host a pre-built Docker image on Docker Hub. The image also ships ~2k pre-built packages from a recent Stackage snapshot for convenience of testing simple programs without needing to set up a Cabal project.
To use the image, mount the working directory containing the source code as a
Docker shared volume, then use the ahc-link
program:
username@hostname:~/project$ docker run --rm -it -v $(pwd):/project -w /project terrorjack/asterius
asterius@hostname:/project$ ahc-link --input-hs main.hs
There are a lot of link-time options available to ahc-link
, e.g. targeting
the browser platform instead of node
, adding extra GHC options or setting
runtime parameters. Check the documentation for
further details.
It's also possible to use ahc-cabal
as a drop-in replacement of cabal
to
build a Cabal project. Use ahc-dist
with --input-exe
on the output
"executable" file to generate actual WebAssembly and JavaScript artifacts. See
the diagrams
blog
post for an
example.
Check the official
reference of docker run
to learn more about the command given in the example above. The example
opens an interactive bash
session for exploration, but it's also possible to
use docker run
to invoke the Asterius compiler on local Haskell source files.
Note that podman
can be used instead of docker
here.
Building and using asterius
locally
See the Building guide in the documentation for details.
Hacking on asterius
We recommend using VSCode Remote Containers to reproduce the very same dev environment used by our core team members. The initial container build will take some while, since it will build the whole project and run the boot process. After that, the workflow shall be pretty smooth.
Documentation and blog posts
We have documentation and blog posts:
- Fibonacci compiles end-to-end: Haskell to WebAssembly via GHC
- Haskell WebAssembly calling JavaScript and back again
- Asterius GHC WebAssembly backend reaches TodoMVC
- Haskell art in your browser with Asterius
Also checkout the HIW 2018 lightning talk, and the slides of an introductory talk in 2020 here.
Note that they may be slightly out-of-date as the project evolves. Whenever you find something in the docs of blog posts which doesn't reflect the status quo, it's a bug and don't hesitate to open a ticket :)
What works now
- Almost all GHC language features (TH support is partial, cross-splice state persistence doesn't work yet).
- The pure parts in standard libraries and other packages. IO is achieved via rts primitives or user-defined JavaScript imports.
- Importing JavaScript expressions via the
foreign import javascript
syntax. First-class garbage collectedJSVal
type in Haskell land. - Preliminary copying GC, managing both Haskell heap objects and JavaScript references.
- Preliminary Cabal support.
- Marshaling between Haskell/JavaScript types based on
aeson
. - Calling Haskell functions from JavaScript via the
foreign export javascript
syntax. Haskell closures can be passed between the Haskell/JavaScript boundary viaStablePtr
. - Invoking RTS API on the JavaScript side to manipulate Haskell closures and trigger evaluation.
- A linker which performs aggressive dead-code elimination, producing as small WebAssembly binary as possible.
- A debugger which checks invalid memory access and outputs memory loads/stores and control flow transfers.
- Complete
binaryen
/wabt
raw bindings, plus a monadic EDSL to construct WebAssembly code directly in Haskell. - A Haskell library to handle WebAssembly code, which already powers binary code generation.
- Besides WebAssembly MVP and
BigInt
, no special requirements on the underlying JavaScript engine at the moment.
Sponsors
Asterius is maintained by Tweag I/O.
Have questions? Need help? Tweet at @tweagio.