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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With