Skip to content

Consider integrating into a #lang? #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
countvajhula opened this issue Jan 4, 2025 · 2 comments
Open

Consider integrating into a #lang? #1

countvajhula opened this issue Jan 4, 2025 · 2 comments

Comments

@countvajhula
Copy link

Hello, friend! I found this by way of your recent PR against Racket which, in fact, did help me see the difference between call/cc and call/comp 😄 I've recently been thinking about algebraic effects in the context of #lang experiments and was interested in learning more about call/cc precisely to try my hand at implementing some form of effect system, like what you have here! I'm wondering what expressive error handling provided via a small interface would feel like in a toplevel #lang. If you're interested in trying out any such experiments, I for one would be keen to try it out. Just throwing that out there!

@omentic
Copy link
Owner

omentic commented Feb 20, 2025

Heyo! Sorry, I saw this a while ago but got busy with the start of the term...

I've been thinking about this a lot too. I don't really know. Usability is an issue with effects handlers for sure. They're possibly too far up on the comprehensibility <---> expressiveness graph. They fundamentally break function encapsulation, so how do you mitigate that?

There's two main thoughts I've been kicking around. Effects handlers are very useful: but I think their use is mostly in implementing language features as libraries. If you force the programmer to encapsulate their effects - i.e. disallow the use of try/suspend/resume outside of modules - I think you can get a lot of the benefits and few of the downsides of these systems. Programmers new to a language then do not need to have a conceptual model of continuations, they can just see the exposed generators/exceptions/concurrency interfaces and that they all work together and just think "oh cool, colourless functions". And then if and only if they want to go off and write some library code, they can learn about continuations. (And also importantly, they don't need to inspect every function they use to understand what "resuming" does - because "resuming" has a specific and consistent meaning across these different library interfaces.)

That could be enforced in a #lang. Ultimately though, I think what's equally or more important is a strong types system: with (nearly) total inference and effect tracking across functions. I've played around with a couple of languages in this vein and think Effekt has pretty much got it down... I would lift their types system almost directly (with some changes - explicit iterators don't work great) if I could. But... this doesn't seem like something Racket is very good at, unfortunately... I have only looked briefly at the #lang system (skimmed how-to-hashlang) but it seems like though extending the language is easy, extending the types system is not. Even in Typed Racket. I was going to check out Turnstile, maybe? I had heard that might be useful (and I have wanted an excuse to learn it). Though at that point I don't know whether just implementing a full on new language in Rust or something might be easier.

@countvajhula
Copy link
Author

I'm glad you're thinking about this so deeply. I'm also interested in this from a more mundane standpoint, of just having a nice and rich exception system in a Racket language, and with good syntax. At a minimum, this could just be a basic exception system that only raises and doesn't resume. But the level of expressiveness you have here with suspend and resume is even nicer, and I feel it would be great to find a way to make it practical.

I think having it in an actual #lang would be a useful step, as it would allow us to create concrete examples that demonstrate the problems you've identified, and seeing those problems in real code might suggest targeted, practical solutions. For example, we could explore limited type tracking specifically for the exception/effect system, or experiment with the kinds of module-level (or other) restrictions you've suggested. Even just stern advice in the documentation could alleviate some problems in practice :). These bounded solutions might be more achievable than immediately trying to solve the general theoretical problems (though these theoretical considerations would certainly inform the practical solutions). I too have had Turnstile on my radar but haven't looked into it yet. But I share your suspicion that it may not be easy to deeply extend the type system in Racket, so a full-blown implementation at that level might be impractical.

Re: the #lang tutorial, I just started with the basics in Beautiful Racket, and then with that minimum scaffolding, the rest of it is just writing and providing macros in the appropriate modules. It gets more complicated if you want to extend the language at the reader level, but that doesn't seem necessary.

If you're interested in trying an experiment, the repo I've set up for the purpose makes it pretty easy to get started. Hopefully, after a series of experiments, we could start to synthesize a language (or a few) that incorporates the best of Racket in an accessible, expressive and sound form.

Good luck with your coursework, btw 😝

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants