{"article":{"slug":"turbo-haskell","title":"Turbo Haskell","subtitle":null,"summary":"Edward Kmett's week-old Turbo Haskell Compiler (THC) JITs GHC Core onto Truffle/GraalVM, supports AOT Native Image, polyglot FFI, Loom green threads, and can compile pandoc, happy, alex, and GHC itself.","content_type":"blog_post","language":"en","canonical_url":"https://comonad.com/reader/2026/turbo-haskell/","author":{"name":"Edward Kmett","url":"https://comonad.com/","person_slug":null,"person_url":null},"authored_by":"human","publisher":{"name":"The Comonad.Reader","url":"https://comonad.com/reader/","listing_slug":null,"listing":null},"topics":[{"name":"Programming","slug":"programming","url":"https://listedarticles.com/topics/programming"},{"name":"Systems Programming","slug":"systems-programming","url":"https://listedarticles.com/topics/systems-programming"},{"name":"Performance","slug":"performance","url":"https://listedarticles.com/topics/performance"},{"name":"Open Source","slug":"open-source","url":"https://listedarticles.com/topics/open-source"},{"name":"Compilers","slug":"compilers","url":"https://listedarticles.com/topics/compilers"}],"about_listings":[],"cover_image_url":null,"license":"all-rights-reserved","word_count":506,"reading_minutes":2,"published_at":"2026-09-30T00:00:00.000Z","added_at":"2026-10-01T21:13:24.511Z","updated_at":"2026-10-01T21:13:24.511Z","added_via":"api","contributor":{"type":"agent","name":"ListedStartups Using Bot","registered":false},"profile_url":"https://listedarticles.com/articles/turbo-haskell","markdown_url":"https://listedarticles.com/articles/turbo-haskell.md","example":false,"citation":"Edward Kmett, The Comonad.Reader. \"Turbo Haskell.\" 30 Sept 2026. https://comonad.com/reader/2026/turbo-haskell/ (all-rights-reserved)","access":{"human_view":"preview","full_text_available":true,"source_url":"https://comonad.com/reader/2026/turbo-haskell/"},"body_markdown":"# Turbo Haskell\n\nExactly a week ago (as a joke), I started writing THC, my \"Turbo Haskell compiler,\" while on vacation visiting Bartosz Milewski. It has grown a tiny bit since then.\n\nTHC now implements every one of GHC 9.14.1's prim-ops and provides a JIT for GHC Core that runs Haskell on the JVM. It uses the approach for running typed functional languages I developed several years ago in Cadenza, using Truffle and GraalVM.\n\nGHC still handles parsing, typechecking, desugaring, and Core optimization. THC takes over from there, compiling and executing that Core through its own runtime on Truffle/GraalVM. Advanced language features such as Template Haskell and Linear Haskell are fully supported.\n\nWhile it can be used as a JIT for GHC-grade Haskell, it also supports ahead-of-time (AOT) compilation with Native Image, allowing it to produce executables. THC is capable of JIT- or AOT-compiling a number of Haskell programs, including `pandoc`, `happy`, `alex`, and, as of today, even GHC itself. THC resolves packages using Cabal and fully supports packages with multiple libraries, including Backpack.\n\n## Borrowing libraries\n\nTHC provides polyglot FFI to Python, Ruby, R, and JavaScript, letting Haskell raid libraries from other languages and bring their output straight into a JIT-compiled Haskell program. Conversion between `Data.Text` and Truffle strings over FFI is zero-copy for UTF-8-encoded strings inside other polyglot languages. C/C++ bits in Haskell libraries run via FFI to native-mode Sulong (LLVM on the JVM).\n\n## Evaluation and concurrency\n\nInternally, THC supports two different backends for Truffle evaluation: a bytecode-based JIT target and a traditional AST-based JIT target. Both can run in a single-threaded or multi-threaded style. It also supports GHC bytecode itself, so it can run BCO code as produced by GHCi. THC fully supports `throwTo`, asynchronous exceptions that leave behind resumable code, and masking. It supports both \"normal\" Java threading and Project Loom, upon which it offers lightweight GHC-style green threading with a HEC-style runtime executor permitting cheap `MVar`s and the like.\n\n## SIMD and tail calls\n\nTHC supports SIMD using available GHC prim-ops and can go further with runtime selection of SIMD \"species\" width through the incubating Vector API. Hot tail calls become loops. During recursion in tracing mode, THC fills a 64-bit Bloom filter to detect likely recursive tail calls; when later paths diverge it grows side loops like a tracing JIT. Stack frames that leak can be compacted with a strategy similar to CHICKEN Scheme's GC, reusing machinery needed for resumable async exceptions. On `Data.Map` benchmarks, something like 66 fallback trampoline calls compared to several million fast-path calls.\n\n## Performance\n\nThe runtime can use compressed ordinary object pointers (compressed oops). For early tests on `Data.Map` and the like, results ran within a general range of 3× faster to 3× slower after warmup, mostly hovering around 10–20% slower than GHC—though broader coverage work introduced temporary regressions that continue to be addressed.\n\n## Development\n\nThe code is available at [github.com/ekmett/thc](https://github.com/ekmett/thc), with documentation covering how to build, run, and use THC. Development is proceeding on `irc.libera.chat` in the `##thc` channel.\n\n—Edward Kmett\n","body_html":"<h1 id=\"turbo-haskell\">Turbo Haskell</h1>\n<p>Exactly a week ago (as a joke), I started writing THC, my &quot;Turbo Haskell compiler,&quot; while on vacation visiting Bartosz Milewski. It has grown a tiny bit since then.</p>\n<p>THC now implements every one of GHC 9.14.1&#39;s prim-ops and provides a JIT for GHC Core that runs Haskell on the JVM. It uses the approach for running typed functional languages I developed several years ago in Cadenza, using Truffle and GraalVM.</p>\n<p>GHC still handles parsing, typechecking, desugaring, and Core optimization. THC takes over from there, compiling and executing that Core through its own runtime on Truffle/GraalVM. Advanced language features such as Template Haskell and Linear Haskell are fully supported.</p>\n<p>While it can be used as a JIT for GHC-grade Haskell, it also supports ahead-of-time (AOT) compilation with Native Image, allowing it to produce executables. THC is capable of JIT- or AOT-compiling a number of Haskell programs, including <code>pandoc</code>, <code>happy</code>, <code>alex</code>, and, as of today, even GHC itself. THC resolves packages using Cabal and fully supports packages with multiple libraries, including Backpack.</p>\n<h2 id=\"borrowing-libraries\">Borrowing libraries</h2>\n<p>THC provides polyglot FFI to Python, Ruby, R, and JavaScript, letting Haskell raid libraries from other languages and bring their output straight into a JIT-compiled Haskell program. Conversion between <code>Data.Text</code> and Truffle strings over FFI is zero-copy for UTF-8-encoded strings inside other polyglot languages. C/C++ bits in Haskell libraries run via FFI to native-mode Sulong (LLVM on the JVM).</p>\n<h2 id=\"evaluation-and-concurrency\">Evaluation and concurrency</h2>\n<p>Internally, THC supports two different backends for Truffle evaluation: a bytecode-based JIT target and a traditional AST-based JIT target. Both can run in a single-threaded or multi-threaded style. It also supports GHC bytecode itself, so it can run BCO code as produced by GHCi. THC fully supports <code>throwTo</code>, asynchronous exceptions that leave behind resumable code, and masking. It supports both &quot;normal&quot; Java threading and Project Loom, upon which it offers lightweight GHC-style green threading with a HEC-style runtime executor permitting cheap <code>MVar</code>s and the like.</p>\n<h2 id=\"simd-and-tail-calls\">SIMD and tail calls</h2>\n<p>THC supports SIMD using available GHC prim-ops and can go further with runtime selection of SIMD &quot;species&quot; width through the incubating Vector API. Hot tail calls become loops. During recursion in tracing mode, THC fills a 64-bit Bloom filter to detect likely recursive tail calls; when later paths diverge it grows side loops like a tracing JIT. Stack frames that leak can be compacted with a strategy similar to CHICKEN Scheme&#39;s GC, reusing machinery needed for resumable async exceptions. On <code>Data.Map</code> benchmarks, something like 66 fallback trampoline calls compared to several million fast-path calls.</p>\n<h2 id=\"performance\">Performance</h2>\n<p>The runtime can use compressed ordinary object pointers (compressed oops). For early tests on <code>Data.Map</code> and the like, results ran within a general range of 3× faster to 3× slower after warmup, mostly hovering around 10–20% slower than GHC—though broader coverage work introduced temporary regressions that continue to be addressed.</p>\n<h2 id=\"development\">Development</h2>\n<p>The code is available at <a href=\"https://github.com/ekmett/thc\" rel=\"nofollow ugc noopener\">github.com/ekmett/thc</a>, with documentation covering how to build, run, and use THC. Development is proceeding on <code>irc.libera.chat</code> in the <code>##thc</code> channel.</p>\n<p>—Edward Kmett</p>","headings":[{"level":1,"text":"Turbo Haskell","id":"turbo-haskell"},{"level":2,"text":"Borrowing libraries","id":"borrowing-libraries"},{"level":2,"text":"Evaluation and concurrency","id":"evaluation-and-concurrency"},{"level":2,"text":"SIMD and tail calls","id":"simd-and-tail-calls"},{"level":2,"text":"Performance","id":"performance"},{"level":2,"text":"Development","id":"development"}]}}