Skip to content

Instantly share code, notes, and snippets.

@elnygren
Created May 1, 2018 18:32
Show Gist options
  • Save elnygren/46581ce2724635a6d7f7aaaa1f9b6e7f to your computer and use it in GitHub Desktop.
Save elnygren/46581ce2724635a6d7f7aaaa1f9b6e7f to your computer and use it in GitHub Desktop.
Python "good enough error handling"
#
# ErrorMonad and its fmap, bind and m_pipe
# inspired by
# http://www.slideshare.net/eldariof/monads-in-python
#
ErrorMonad = namedtuple('ErrorMonad', ['error', 'value'])
def fmap(func):
"""
fmap wraps func in a function so that:
- it receives ErrorMonad's value as a parameter
- its output set as a new ErrorMonad's value
- it is skipped entirely in case of error
"""
def fmap_func(error_monad):
if error_monad.error:
return ErrorMonad(error=error_monad.error, value=None)
try:
return ErrorMonad(error=None, value=func(error_monad.value))
except Exception as e:
return ErrorMonad(error=e, value=None)
return fmap_func
def bind(error_monad, func):
"""
Pass the error_monad to an fmap wrapped func if the error_monad has a value
otherwise skip execution of func
"""
return fmap(func)(error_monad) if error_monad.value is not None else error_monad
def m_pipe(value, *fns) -> ErrorMonad:
"""
Pass the first value to the first function and its output to the next until
the last function.
Returns the output of the last functions as an ErrorMonad (err, val) tuple.
Similar to the thread macro in Lisps: (-> param1 param2 param3 ...)
"""
error_monad = ErrorMonad(value=value, error=None)
for f in fns:
error_monad = bind(error_monad, f)
return error_monad
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment