Created
October 5, 2017 18:10
-
-
Save jordanyaker/2850956fea18a3f3b65b13ef0c0cbe7d to your computer and use it in GitHub Desktop.
Try-Monad
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# ------------------------------------------------------------ | |
# Based on Jason DeLaat's Either monad: | |
# https://github.com/fnl/pymonad/blob/master/pymonad/Either.py | |
# ------------------------------------------------------------ | |
from pymonad.Monad import * | |
class Try(Monad): | |
""" | |
Represents an operation that may either fail or succeed. | |
An alternative to using exceptions. 'Try' is an abstract type and should not | |
be instantiated directly. Instead use 'Success' and 'Failure'. | |
""" | |
def __init__(self, value): | |
""" Raises a 'NotImplementedError'. Use 'Success' or 'Failure' instead. """ | |
raise NotImplementedError | |
def __eq__(self, other): | |
if not isinstance(other, Try): raise TypeError("Can't compare different types.") | |
@classmethod | |
def unit(cls, value): | |
return Success(value) | |
@property | |
def is_success(self): | |
return False | |
@property | |
def is_failure(self): | |
return False | |
class Failure(Try): | |
""" | |
Represents an operation which has failed and contains an error code or message. | |
To help with readaility you may alternatively use the alias 'Error'. | |
""" | |
def __init__(self, errorMsg): | |
""" | |
Creates a 'Failure' "operation failed" object. | |
'errorMsg' can be anything which gives information about what when wrong. | |
""" | |
super(Try, self).__init__(errorMsg) | |
def __eq__(self, other): | |
super(Failure, self).__eq__(other) | |
if not isinstance(other, Failure): | |
return False | |
elif self.getValue() == other.getValue(): | |
return True | |
else: | |
return False | |
def __ne__(self, other): | |
return not self.__eq__(other) | |
def __str__(self): | |
return "Failure: " + str(self.getValue()) | |
def fmap(self, _): | |
""" Returns the 'Failure' instance that was used to call the method. """ | |
return self | |
def amap(self, _): | |
""" Returns the 'Failure' instance that was used to call the method. """ | |
return self | |
def bind(self, _): | |
""" Returns the 'Failure' instance that was used to call the method. """ | |
return self | |
@property | |
def is_failure(self): | |
return True | |
class Success(Try): | |
""" | |
Represents an operation which has succeeded and contains the result of that operation. | |
""" | |
def __init__(self, value): | |
""" | |
Creates a 'Success' "operation succeeded" object. | |
'value' is the actual calculated value of whatever operation was being performed | |
and can be any type. | |
""" | |
super(Try, self).__init__(value) | |
def __eq__(self, other): | |
super(Success, self).__eq__(other) | |
if not isinstance(other, Success): | |
return False | |
elif self.getValue() == other.getValue(): | |
return True | |
else: | |
return False | |
def __ne__(self, other): | |
return not self.__eq__(other) | |
def __str__(self): | |
return "Success: " + str(self.getValue()) | |
def fmap(self, function): | |
""" | |
Applies 'function' to the contents of the 'Success' instance and returns a | |
new 'Success' object containing the result. | |
'function' should accept a single "normal" (non-monad) argument and return | |
a non-monad result. | |
""" | |
return Success(function(self.getValue())) | |
def amap(self, functor_value): | |
"""Applies the function stored in the functor to 'functor_value'. | |
Args: | |
functor_value: A function to be applied. | |
Returns: | |
pymonad.Monad.Try: A new Try value. | |
""" | |
return self.getValue() * functor_value | |
def bind(self, function): | |
""" | |
Applies 'function' to the result of a previous operation. | |
'function' should accept a single "normal" (non-monad) argument and return | |
either a 'Failure' or 'Success' type object. | |
""" | |
return function(self.getValue()) | |
@property | |
def is_success(self): | |
return True |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment