Java FFI can be done, it is just on the messier end of the spectrum. I do a little bit of it as needed, but I've focused in on Polyglot languages for now, and deferred a lot of the hooks for nicely handling it to later work.
Talking about Java FFI invites you to say 'well then smart-ass how do you extend this Java class/interface over here with code written in your language' and frankly, that has never had a satisfying answer for any language that isn't Java.
But today you can pass Haskell Data.Text out through the FFI binding framework and it shows up on the other side as a valid TruffleString, in UTF-8 with zero copy semantics and if any Truffle language passes in a TruffleString that is UTF-8 encoded it gets unwrapped into Data.Text using the same.
That and some array support is pretty much enough to talk to everybody else.
Only tangentially related, but I'm reminded of Frege[0], a Haskell dialect for the JVM that I stumbled across at one point and thought looked really cool.... I see recent commits but the releases are all really old, so I can't tell what the state of the project is.
I hadn't thought of Fregue in some years! I helped them with their logo and some smaller issues back in the time. I will check out the latest commits to see what's being updated (hopefully not only dependabot:) ).
Since there is MicroHS Haskell compiler in 0.5 MB space nothing is stopping people to wire it together with TurboVision/ncurses. Apart from that the name is taken now.
A warm, running GHCi parses, compiles (to byte-code) and executes simple snippets in 10ms on Codespaces. It's not big project compilation, but a rapid change->result cycle should be possible with GHC.
Part of the name was a joke about people often mishearing Haskell as Pascal, Ed told me a couple of years ago. I think it might have been at ZuriHac back when it was at Google Zurich, so 2016-ish?
Kmett is a legend in Haskell. He writes and maintains tens of libraries - since the 2000s. Even before LLMs, Kmett had an output like most of us can do only with LLMs. Seriously, the guy is a coding machine.
now that there's all the rage about agentic coding - & languages don't matter - why r people not migrating to more less error prone languages like Haskell ?
I've had much better experiences with Haskell (well, mostly PureScript for now) than Python, but that might be because I am very hands-on with the design of the core types and abstractions I'm working with.
Having an effect system so that Claude is not tempted to throw in side-effects everywhere helps a lot too!
(For further context, I was comparing essentially vibe code across languages. Vibe-coded Clojure stood out as much less unpalatable than anything else I tried.)
The pre-LLM popularity of languages remains sticky because it influences what libraries are available, the sophistication of the tooling, and of course, sticky developer preferences. So while the playing fields may shift a little, it resembles what came before. In my circles I've noticed it's very easy for us to rationalize why our previous favorite language is also the perfect language for the agent era.
If your favorite language before was Python, why, LLMs are fluent in it! So much training data! So many libraries! Home of machine learning! None of that pesky compile time, agents don't need compile time safety anyway, they write such good test coverage! It's The Perfect Agentic Coding Language.
If it was Rust, by jove, an agent can easily handle the headache of satisfying the borrow checker, and now you get the best of all worlds! Safety! Near-C runtime performance! Abstractions! The only reason people didn't use Rust before was it was Too Hard and there were Too Many Furries and now it's not hard and you don't have to interact with them, so get on board. It's The Perfect Agentic Coding Language.
If it was Golang, oh my goodness, what a choice. Pretty fast compile time and pretty fast runtime. Agents get a tight feedback loop with build->run->test->edit. Not very complicated, code has to be written in a straightforward banging-rocks-together way. Good stable ecosystem! Rob Pike designed the language for people he said were "not capable of understanding a brilliant language but we want to use them to build good software." That's an arrogant, demeaning way to describe your colleagues but if they're LLM agents it's dead on! It's The Perfect Agentic Coding Language.
I could go on and on. I'm not immune either! My own favorite language is F# and I play the same game:
It has access to the .NET ecosystem like C#, but I don't have to constantly remind the agents to prefer a style with immutable data and pure functions, they idiomatically do that in F#. Files have to be in order and can only refer to symbols defined "earlier" in order, if you want mutually-referential types or functions they have to be declared as such in a joint statement, so spaghetti is hard to create: each project's codebase naturally ends up in a layered bottom-to-top architecture. The language is terse enough to be token efficient, without being symbol soup. FSX scripts can be generated during agentic code reviews to demonstrate repros for discovered issues. If there's any type of code that still warrants me jumping in and writing some myself, that code would be data type definitions/domain modelling, and F# is a joy to write those in. It's The Perfect Agentic Coding Language.
Because a) the LLMs are pretty good at Java and what not, and b) the LLMs are less good at more rarely used programming languages since there is less material on those to train on.
https://github.com/ekmett/hide takes on that part of the project (formerly thc-edit mentioned in a couple of other replies). Not Turbo Vision based per se, but has that same classic style of UI. It renders itself via terminal, metal, vulkan or webgl UI and provides editor services, AI agent support, autocomplete, and can connect to another instance over SSH to provide these presentation services over the network.
Text is presented in a faux IBM VGA font, blue background, and in any of the non-terminal choices a subtle CRT grading/vignetting is applied if desired, but it is extended to full unicode including emoji with an optional stylization pass to make them feel more like the period editor experience. You can even switch display modes because most of the time I used Borland tools in my youth I'd run them in 80x50 mode.
My general intent is that the final installer will package both of them, just like Turbo Pascal bundled TP and TPC or Turbo C bundled TC and TCC.
> THC 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
Look, it's very cool and a great project, but I just don't think you should call the compiler "turbo $something" if you're not going to make it a TUI IDE.
Wow, such a typical Haskell thing. There's a project with zero explanation with a pragmatic angle, and even asking questions about it is discouraged. What's the downvote for? I get it, Haskell on JVM, but what's the point? What kind of personal or maybe well-known and recognized itch Kmeth is trying to solve here? No? We, the mere mortals are not worthy to know that, until we reach the "enlightenment phase"?
We get a JITTed runtime, which can actually beat compiled GHC in performance in cases.
We get first-class cross-language FFI to truffled language implementations: Python, Ruby, R, Javascript with shared objects, which can JIT together. The idea is that fully fleshed out this would give Haskell a clean path to reach over to pytorch to run an AI model, take the answers, smash them through some statistical analysis using an obscure R library and send the result to d3.js to get pretty visualizations. Are we there yet? Hell no.
We get access to the java incubator vector API allowing us to JIT SIMD kernels for the target platform with less pain. Haskell has just been bad at high speed SIMD code since I found my way into the ecosystem, and it hasn't shown much sign of getting better. This lets me theoretically sidestep those issues.
Using Sulong for C/C++ FFI means we don't give up native cbits and host code, unlike old bad hard-to-use JVM language ports like JPython.
Future work could for instance make Natural number code use java deoptimization paths keeping it generally in unboxed ints until you finally need something too big through a given codepath. Again, just more paths to potentially make things faster or easier to use.
Without Truffle/Graal the limitations of the JVM are just too severe. It is an awkward runtime full of limitations. The lack of proper tail call optimization for instance would kill GHC-style evaluation performance, and has left a long list of functional language corpses in its wake that tried to make the JVM their home.
With the "Cadenza trick" I use to eliminate that we can have highly performant loops. Using assumptions lets it compile with the equivalent of GHC's single threaded runtime and then downgrade performance to the equivalent of the multi-threaded runtime when you first call a threading operation, so users don't have to pick, they just get the benefits. I, in turn, get headaches.
We get stuff that GHC just will never even try to get around to. CompressedOOPS give us 32 bit pointers on 64 bit platforms if the heap is < ~32GB. So about twice as much stuff can fit into cache especially in a language with as many pointers running around as ours compared to the normal Haskell runtime.
My goal is to keep pushing forward with the bits that this can do that GHC can't do, and to generally try to get to or maintain parity wherever possible for the things that GHC can do.
It also helps us tease apart where the line should be for GHC as a runtime system vs. GHC as a compiler. The former has been languishing behind comparatively, ever since Simon Marlow left GHC headquarters to go fight spam for Meta.
I wrote a blog post targeted at an insider audience to tease at something that was coming. It has since spread outside of that audience. There's no gatekeeping going on here, no secret enlightenment required, just a poorly drafted research note thrown over the fence to his peers to see if anybody else might be interested in his new favorite toy by a very busy person. I'm sorry.
You can FFI out to/from java and should be able to talk to clojure through that. Not exactly the most fleshed out part of the API at present, but the bones are there.
52 comments
[ 0.29 ms ] story [ 47.5 ms ] threadBut of course as a Truffle language it gets "free" java interop
Talking about Java FFI invites you to say 'well then smart-ass how do you extend this Java class/interface over here with code written in your language' and frankly, that has never had a satisfying answer for any language that isn't Java.
But today you can pass Haskell Data.Text out through the FFI binding framework and it shows up on the other side as a valid TruffleString, in UTF-8 with zero copy semantics and if any Truffle language passes in a TruffleString that is UTF-8 encoded it gets unwrapped into Data.Text using the same.
That and some array support is pretty much enough to talk to everybody else.
[0] https://github.com/frege/frege
A warm, running GHCi parses, compiles (to byte-code) and executes simple snippets in 10ms on Codespaces. It's not big project compilation, but a rapid change->result cycle should be possible with GHC.
Now picking CBD for the compressed Core Binary Distribution format we use? That? That was gratuitous.
i am not sure anyone actually understands what is going on under the hood of the project. looks like average slop.
>> Exactly a week ago (as a joke), I started writing THC,
you? i hope you have read at least something of what your agent wrote about the project.
How can you tell?
https://www.reddit.com/r/haskell/comments/1wu24oe/turbo_hask...
Why not call it Jaskell then?
https://haskell.foundation/podcast/87/
I have no doubt the haskell compiles… but when it comes from an LLM it reads like nonsensical code soup.
Claude-generated Clojure seems a lot better.
Having an effect system so that Claude is not tempted to throw in side-effects everywhere helps a lot too!
(For further context, I was comparing essentially vibe code across languages. Vibe-coded Clojure stood out as much less unpalatable than anything else I tried.)
If your favorite language before was Python, why, LLMs are fluent in it! So much training data! So many libraries! Home of machine learning! None of that pesky compile time, agents don't need compile time safety anyway, they write such good test coverage! It's The Perfect Agentic Coding Language.
If it was Rust, by jove, an agent can easily handle the headache of satisfying the borrow checker, and now you get the best of all worlds! Safety! Near-C runtime performance! Abstractions! The only reason people didn't use Rust before was it was Too Hard and there were Too Many Furries and now it's not hard and you don't have to interact with them, so get on board. It's The Perfect Agentic Coding Language.
If it was Golang, oh my goodness, what a choice. Pretty fast compile time and pretty fast runtime. Agents get a tight feedback loop with build->run->test->edit. Not very complicated, code has to be written in a straightforward banging-rocks-together way. Good stable ecosystem! Rob Pike designed the language for people he said were "not capable of understanding a brilliant language but we want to use them to build good software." That's an arrogant, demeaning way to describe your colleagues but if they're LLM agents it's dead on! It's The Perfect Agentic Coding Language.
I could go on and on. I'm not immune either! My own favorite language is F# and I play the same game:
It has access to the .NET ecosystem like C#, but I don't have to constantly remind the agents to prefer a style with immutable data and pure functions, they idiomatically do that in F#. Files have to be in order and can only refer to symbols defined "earlier" in order, if you want mutually-referential types or functions they have to be declared as such in a joint statement, so spaghetti is hard to create: each project's codebase naturally ends up in a layered bottom-to-top architecture. The language is terse enough to be token efficient, without being symbol soup. FSX scripts can be generated during agentic code reviews to demonstrate repros for discovered issues. If there's any type of code that still warrants me jumping in and writing some myself, that code would be data type definitions/domain modelling, and F# is a joy to write those in. It's The Perfect Agentic Coding Language.
Text is presented in a faux IBM VGA font, blue background, and in any of the non-terminal choices a subtle CRT grading/vignetting is applied if desired, but it is extended to full unicode including emoji with an optional stylization pass to make them feel more like the period editor experience. You can even switch display modes because most of the time I used Borland tools in my youth I'd run them in 80x50 mode.
My general intent is that the final installer will package both of them, just like Turbo Pascal bundled TP and TPC or Turbo C bundled TC and TCC.
Look, it's very cool and a great project, but I just don't think you should call the compiler "turbo $something" if you're not going to make it a TUI IDE.
Next?
We get first-class cross-language FFI to truffled language implementations: Python, Ruby, R, Javascript with shared objects, which can JIT together. The idea is that fully fleshed out this would give Haskell a clean path to reach over to pytorch to run an AI model, take the answers, smash them through some statistical analysis using an obscure R library and send the result to d3.js to get pretty visualizations. Are we there yet? Hell no.
We get access to the java incubator vector API allowing us to JIT SIMD kernels for the target platform with less pain. Haskell has just been bad at high speed SIMD code since I found my way into the ecosystem, and it hasn't shown much sign of getting better. This lets me theoretically sidestep those issues.
Using Sulong for C/C++ FFI means we don't give up native cbits and host code, unlike old bad hard-to-use JVM language ports like JPython.
Future work could for instance make Natural number code use java deoptimization paths keeping it generally in unboxed ints until you finally need something too big through a given codepath. Again, just more paths to potentially make things faster or easier to use.
Without Truffle/Graal the limitations of the JVM are just too severe. It is an awkward runtime full of limitations. The lack of proper tail call optimization for instance would kill GHC-style evaluation performance, and has left a long list of functional language corpses in its wake that tried to make the JVM their home.
With the "Cadenza trick" I use to eliminate that we can have highly performant loops. Using assumptions lets it compile with the equivalent of GHC's single threaded runtime and then downgrade performance to the equivalent of the multi-threaded runtime when you first call a threading operation, so users don't have to pick, they just get the benefits. I, in turn, get headaches.
We get stuff that GHC just will never even try to get around to. CompressedOOPS give us 32 bit pointers on 64 bit platforms if the heap is < ~32GB. So about twice as much stuff can fit into cache especially in a language with as many pointers running around as ours compared to the normal Haskell runtime.
My goal is to keep pushing forward with the bits that this can do that GHC can't do, and to generally try to get to or maintain parity wherever possible for the things that GHC can do.
It also helps us tease apart where the line should be for GHC as a runtime system vs. GHC as a compiler. The former has been languishing behind comparatively, ever since Simon Marlow left GHC headquarters to go fight spam for Meta.
I wrote a blog post targeted at an insider audience to tease at something that was coming. It has since spread outside of that audience. There's no gatekeeping going on here, no secret enlightenment required, just a poorly drafted research note thrown over the fence to his peers to see if anybody else might be interested in his new favorite toy by a very busy person. I'm sorry.