Skip to content

Instantly share code, notes, and snippets.

@aaronchall
Created August 24, 2019 20:35
Show Gist options
  • Save aaronchall/27f5cb71a760da2da99fd69c954e3df4 to your computer and use it in GitHub Desktop.
Save aaronchall/27f5cb71a760da2da99fd69c954e3df4 to your computer and use it in GitHub Desktop.
Python monads, WIP
from __future__ import annotations
from abc import ABC, abstractmethod, abstractproperty
from functools import partial
def main():
a = 1
b = a + 1 # bind a in b,
c = b * 2 # bind b in c, etc...
d = c ** 3
print(d)
em = EagerMonad(1) # not
result = em | add1 | identity | times2 | power3 | to_str | identity
print(result.a)
#lm = LazyMonad(1)
#result2 = lm | identity | add1 | power3 | times2
#print(result2().a)
def add1(a: object) -> Monad:
b = a + 1
return EagerMonad(b)
def times2(a: object) -> Monad:
b = a * 2
return EagerMonad(b)
def power3(a: object) -> Monad:
b = a ** 3
return EagerMonad(b)
def to_str(a: object) -> Monad:
b = str(a)
return EagerMonad(b)
def identity(b) -> Monad:
"""monadic identity function"""
return EagerMonad(b)
class Monad(ABC):
@abstractproperty
def a(self):
raise AttributeError('a is not implemented for this AbstractMonad')
@abstractmethod
def __init__(self, a):
self.a = a
@abstractmethod
def bind(self: Monad, function: MonadicFunction) -> Monad:
"""given a unary (i.e. a monadic) function that takes a single argument, `a`
and returns a monad (containing potentially another type),
return the result of passing `a` to that function
"""
return function(self.a)
def __or__(self, fn):
"""allows `Monad(a) | f | g | h` ..."""
return self.bind(fn)
class EagerMonad(Monad):
__slots__ = 'a'
def __init__(self, a):
self.a = a
def bind(self, function):
return function(self.a)
class LazyMonad(Monad):
__slots__ = 'a', 'thunk'
def __init__(self, a):
self.a = a
def bind(self, function):
self.thunk = partial(function, self.a)
def __call__(self):
return self.thunk()
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment