Skip to content

Instantly share code, notes, and snippets.

@L3viathan
Created September 20, 2022 19:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save L3viathan/e9ab7839f148c8be0a0c22307d75e682 to your computer and use it in GitHub Desktop.
Save L3viathan/e9ab7839f148c8be0a0c22307d75e682 to your computer and use it in GitHub Desktop.
Simple demo of algebraic effects in Python. This doesn't show the full potential; it's just a proof-of-concept
import sys
class Effect:
def __enter__(self):
self.local_handlers = sys._getframe().f_back.f_locals.setdefault("_effect_handlers", [])
self.local_handlers.append(self)
def __exit__(self, *args):
self.local_handlers.pop()
def __call__(self, key, *args, **kwargs):
if hasattr(self, f"handle_{key}"):
return getattr(self, f"handle_{key}")(*args, **kwargs)
elif hasattr(self, "handle"):
return getattr(self, "handle")(*args, **kwargs)
return NotImplemented
class Printer(Effect):
def __init__(self, prefix):
self.prefix = prefix
def handle_print(self, val):
print(self.prefix, val)
def perform(value, *args, **kwargs):
frame = sys._getframe()
handled = False
while frame := frame.f_back:
if "_effect_handlers" in frame.f_locals:
for handler in reversed(frame.f_locals["_effect_handlers"]):
if (retval := handler(value, *args, **kwargs)) is not NotImplemented:
return retval
raise RuntimeError("unhandled effect")
def something():
perform("print", "hello")
with Printer("outer"):
something()
with Printer("inner"):
something()
something()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment