Skip to content

Instantly share code, notes, and snippets.

@pavdwest
Last active July 10, 2022 20:09
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 pavdwest/a65d0f779293c427246068b29ee5e4e8 to your computer and use it in GitHub Desktop.
Save pavdwest/a65d0f779293c427246068b29ee5e4e8 to your computer and use it in GitHub Desktop.
Python MaybeMonad
from __future__ import annotations
from asyncio.log import logger
from typing import Callable
class MaybeMonad():
def __init__(
self,
value: object
) -> None:
self.value = value
def bind(
self,
func: Callable,
*args
) -> MaybeMonad:
if not self.is_valid():
return MaybeMonad(None)
try:
self.value = func(self.value, *args)
return self
except Exception as e:
logger.warning(f"Binding '{func.__name__}' raised exception '{e}'. Your monad is now invalid.")
return MaybeMonad(None)
def is_valid(self):
return (self.value != None)
def __str__(self):
return str(self.value)
# Some functions you need to chain.
def get_user(id: int):
return "Geoff"
def add_title(name: str, title: str):
return f"{title}. {name}"
def add_suffix(name: str, suffix: str):
raise Exception("EVIL NULL!") # Raise exception to illustrate. Uncomment for success.
# return f"{name} {suffix}." # Uncomment for success
def greet(name: str):
return f"Hello {name}"
# Main
def main():
greeting = MaybeMonad(get_user(id=1)) \
.bind(add_title, "Dr") \
.bind(add_suffix, "jr") \
.bind(greet)
print(str(greeting))
if __name__ == '__main__':
main()
@pavdwest
Copy link
Author

Using *args is pretty nice as it allows binding functions with n params.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment