Skip to content

Instantly share code, notes, and snippets.

@cleac
Created August 13, 2019 18:27
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 cleac/f30d99ac9df31a8383766e9b2eaf97d8 to your computer and use it in GitHub Desktop.
Save cleac/f30d99ac9df31a8383766e9b2eaf97d8 to your computer and use it in GitHub Desktop.
Some monads in python
class Monad:
def __init__(self, value):
self.value = value
def __iter__(self):
yield self
def do(self):
raise NotImplementedError()
def join(self):
if isinstance(self.value, self.__class__):
return self.value.join()
return self
class IO(Monad):
def __init__(self, value):
if callable(value) and not isinstance(value, self.__class__):
self.predicate = value
self.value = None
else:
self.value = value
self.predicate = lambda: self.value
def __repr__(self):
if not self.value:
return f'{self.__class__.__name__}(<uncalculated>)'
return f'{self.__class__.__name__}({self.value})'
def do(self):
self.value = self.join().predicate()
return self.value
def __add__(self, value):
return self.__class__(lambda: self.do() + value)
def __eq__(self, value):
return self.__class__(lambda: self.do() == value)
def __ne__(self, value):
return self.__class__(lambda: self.do() != value)
def __iadd__(self, value):
return self + value
def __getattr__(self, name):
return self.__class__(lambda: getattr(self.do(), name))
def __getitem__(self, key, default=None):
return self.__class__(lambda: self.do().get(key, default))
def __call__(self, *args, **kwargs):
return self.__class__(lambda: self.predicate()(*args, **kwargs))
class Option(Monad):
def __repr__(self):
if self.value:
return f'Some({self.value})'
return 'None'
def __bool__(self):
return self.value
def __add__(self, value):
if not self.value:
return self
return self.__class__(self.value + value)
def __eq__(self, value):
if not self.value:
return self
return self.__class__(self.do() == value)
def __ne__(self, value):
if not self.value:
return self
return self.__class__(self.do() != value)
def __iadd__(self, value):
if not self.value:
return self
return self + value
def __getattr__(self, name):
if not self.value:
return self
return self.__class__(getattr(self.do(), name))
def __getitem__(self, key, default=None):
if not self.value:
return self
return self.__class__(self.do().get(key, default))
def __call__(self, *args, **kwargs):
if not self.value:
return self
return self.__class__(self.do()(*args, **kwargs))
def do(self):
return self.join().value
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment