Created
November 18, 2021 17:42
-
-
Save luther9/b55d0f988a8da2c8728a9534cd3acb74 to your computer and use it in GitHub Desktop.
IO monad in Python
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from collections.abc import Callable | |
from dataclasses import dataclass | |
import traceback | |
@dataclass(frozen=True) | |
class IO: | |
_action: Callable | |
allowedExceptions: tuple = () | |
@classmethod | |
def unit(cls, x): | |
return cls(lambda: x) | |
@classmethod | |
def wrap(cls, f, allowedExceptions=()): | |
return lambda *args, **kwargs: cls( | |
lambda: f(*args, **kwargs), | |
allowedExceptions, | |
) | |
def __call__(self): | |
try: | |
return self._action() | |
except self.allowedExceptions as e: | |
return e | |
def bind(self, f): | |
return IO(lambda: f(self())()) | |
def seq(self, other): | |
"""Equivalent to self.bind(lambda x: other).""" | |
@IO | |
def action(): | |
self() | |
return other() | |
return action | |
IO.done = IO.unit(None) | |
ioInput = IO(input, EOFError) | |
ioPrint = IO.wrap(print) | |
def echoLoop(s): | |
return IO.done if isinstance(s, EOFError) else ioPrint(s).seq(echo) | |
echo = ioInput.bind(echoLoop) | |
echo() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment