Maybe monad in Python with method chaining
exception, method-chaining, monads, option-type, python
Solution
The downside to this is that it intentionally suppresses errors, which is generally considered a bad idea in python.
However, you can catch and store any errors occur in your `Maybe` instance and report them back.
For example:
class Maybe(object):
def __init__(self, val, error=None):
self.val = val
self.error = error
def __repr__(self):
if self.val is not None:
return repr(self.val)
else:
return repr(self.error)
def do(self, func):
if self.val is None:
return self
try:
return Maybe(func(self.val))
except Exception as e:
return Maybe(None, e)
def squared(x):
return x * x
def addone(x):
return x + 1
result1 = Maybe(5).do(squared).do(addone)
result2 = Maybe('a').do(squared).do(addone)
print result1
print result2
This yields:
26
TypeError("can't multiply sequence by non-int of type 'str'",)
This is similar to DanD's answer, but has the advantage of storing the error that occurred instead of completely suppressing it.
No matter how you slice it, this idiom is going to feel somewhat "unpythonic", but this is a slightly more robust way of handling it.
Problem
I'm trying to implement the Maybe monad in python. However what I also want is some kind of a chaining ability. So I have a class: ``` class Maybe: def __init__(self, val): self.val = val def do(self, func): # Bind function if self.val is None: return None else: return func(self.val) ``` I have two functions : ``` def double(number): try: result = number * 2 return Maybe(result) except: return Maybe(None) def square(number): try: result = number * number return Maybe(result) except: return Maybe(None) ``` Here's how I'm using this : ``` result = Maybe(5).do(double).do(square) print(result.val) ``` I'm looking at a way to chain multiple functions each performing a specific task. Each function takes the output of the previous function as input. The chain should break if any function in the chain throws an exception. Is this the right way to model the Maybe monad ? Is this the right way to handle exceptions too ? Can this be improved upon ? Thanks a lot.