Die Tests laufen durch und die Klasse tut, was soll. Das heißt aber nichts, diese könnten ja falsch sein bzw. mein Verständnis fehlgeleitet.
Es wäre schön, wenn ihr den folgenden Quelltext einfach mal auseinander nähmet.
Code: Alles auswählen
#!/usr/bin/env python3
import collections
import unittest
class Error(collections.namedtuple('_Error', ['value', 'error'])):
@classmethod
def success(cls, x):
return cls.__new__(cls, x, None)
@classmethod
def fail(cls, why):
return cls.__new__(cls, None, why)
@classmethod
def unit(cls, x):
return cls.success(x)
@classmethod
def bind(cls, mx, mf):
if mx.error is not None: return mx
return mf(mx.value)
def __rshift__(self, mf):
"""API-sugar for the bind-function."""
return self.__class__.bind(self, mf)
def madd_four(x):
return Error.unit(x + 4)
def mmul_three(x):
return Error.unit(x * 3)
class TestErrorMonadLaws(unittest.TestCase):
def test_left_identity_success(self):
x = 5
m = Error.success(x) # success == unit
f = madd_four
assert m >> f == f(x)
def test_right_identity_success(self):
m = Error.success(-2) # success == unit
assert m >> Error.unit == m
def test_associativity_success(self):
m = Error.success(42) # success == unit
f = madd_four; g = mmul_three
assert (m >> f) >> g == m >> (lambda x: f(x) >> g)
def test_left_identity_fail(self):
m = Error.fail('Something went wrong!')
f = madd_four
assert m >> f == m # f(x) won't match as it won't fail.
def test_right_identity_fail(self):
m = Error.fail('Something went wrong!')
assert m >> Error.unit == m
def test_associativity_fail(self):
m = Error.fail('Something went wrong!')
f = madd_four; g = mmul_three
assert (m >> f) >> g == m >> (lambda x: f(x) >> g)
if __name__ == '__main__':
unittest.main()