Hell: shell scripting in Haskell-based language

As a personal indulgence during the Christmas season (in a similar spirit to people who do Advent of Code), I’ve put together a small project that’s been in the back of my mind for years. It’s a small shell scripting language that re-uses Haskell’s syntax and base packages and runtime. Mostly as some kind of weird art project and for myself.

It’s all in one file (which is also an experiment), and doesn’t have a comprehensive list of functions. Or proper error messages, just throws error calls at you.

If you’re somewhat interested in DSLs and language design/compilers, you might get a kick out of it. I certainly did writing it. In particular using Stephanie Weirich’s technique for making a well typed type checker has been a joy.

It was previously a project under the same name that was using shell-conduit, but I never ended up using that for real. But the scripting in Haskell idea still stuck with me.

I’ll be away from tomorrow on vacation until the new year and off the grid, so won’t be able to login to GitHub or anything like that. If you use nix flakes and feel like throwing a config my way, that’d be appreciated. I’m not really doing open source anymore; not enough personal time, so read this as show and tell, not an announcement.

28 Likes

I like the overall idea, but I feel like incantations like ByteString.readProcess (Process.proc "ls" ["-al"]) carry way too much boilerplate for actual shell scripting. That should be expressible as readShell "ls -al" or somesuch.

6 Likes

I think that’s a natural urge. I’m resisting the temptation to come up with new names for things (as one of the two hard problems of CS…), instead deferring the problem to established ecosystem APIs (e.g. the typed-process package - one which I think is a sweet spot of brevity and flexibility). It’s not that easy to come up with a good, memorable, flexible API, though I tried. PowerShell’s Start-Process is similarly long, which is encouraging.

3 Likes

I made a set of slides about Hell’s compiler (from parse, desugar, type infer, type check, eval) for a talk, but they might be of interest here. I could possibly expand them into a blog post if anyone’s interested.

10 Likes

that was a tour de force in embedding functional languages, even for someone with some related experience. A blog post with some actual words between the code blocks and the memes would be much appreciated ^^

5 Likes

I’ve been using Hell for some use cases at work which has really been the proof of the pudding - I really like writing scripts with it, and I’ve written more scripts, that are complex, than I’ve done in the past.

One example is a script that reads Terraform state and all git commits of a particular Terraform file, and computes where all our different deployments are presently at, and then generates a dashboard web page and pushes it to a server.

I slapped together a basic API docs page and examples page (regenerated and published on master CI builds) here Hell: Shell scripting Haskell dialect The polymorphic function type sigs are just TH’s prettyprinter, which is why they’re loud, but I’ll write a tidier one later, with docs.

It’s not there in terms of ergonomics to claim a full release, but thought it might be interesting to see those two pages.

11 Likes

Took me a while, but I did it! Here’s a complete set of notes to go along with the slides:

https://chrisdone.com/posts/tour-of-hell/

16 Likes

very nice and elegant. that was a good read <3

2 Likes