Last active
May 26, 2019 21:26
-
-
Save stojan211287/05f0a3cc1f5531488d5d8c32ffd7d285 to your computer and use it in GitHub Desktop.
Simple Writer monad demo in Python3
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
class Writer: | |
def __init__(self, value, log: str = ""): | |
self._value = value | |
self._log = log | |
# For decorating individual functions with messages | |
@staticmethod | |
def explain(message: str): | |
def decorator(modification: callable): | |
def modification_with_log(*args, **kwargs): | |
return Writer(value=modification(*args, **kwargs), | |
log=message) | |
return modification_with_log | |
return decorator | |
@property | |
def result(self): | |
return self._value | |
@staticmethod | |
def unit(value): | |
return Writer(value) | |
# sig: (A => M[B]) => M[B] | |
def flatMap(self, f): | |
newWriter = f(self._value) | |
return Writer(newWriter._value, self._log+"\n"+newWriter._log) | |
# sig: (A => B) => M[B] | |
def map(self, f): | |
return self.flatMap(lambda value: self.unit(f(value))) | |
def __repr__(self): | |
return f"{self._log}" | |
# So we can use '>>' as a pipe operator | |
def __rshift__(self, writerGenerator: callable): | |
return self.flatMap(writerGenerator) |
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
import monad | |
def writer_test(): | |
def modify(f, msg): | |
return lambda x: monad.Writer(value=f(x), log=msg) | |
pipeline = monad.Writer(2) >> \ | |
modify(lambda x: x+3, "1) Added 3") >> \ | |
modify(lambda x: 4*x, "2) Multiplied by 4") >> \ | |
modify(lambda x: x**2, "3) Raised to the 2nd power") | |
print(f"The result of the pipeline is {pipeline.result}\n") | |
print("The pipeline log is :") | |
print(pipeline) | |
# Pipeline from decorated functions | |
@monad.Writer.explain("1) Added 3") | |
def step1(x): | |
return x+3 | |
@monad.Writer.explain("2) Multiplied by 4") | |
def step2(x): | |
return 4*x | |
@monad.Writer.explain("3) Raised to the 2nd power") | |
def step3(x): | |
return x**2 | |
second_pipeline = monad.Writer(2) >> \ | |
step1 >> \ | |
step2 >> \ | |
step3 | |
print(f"\nDecorator-constructed pipeline yields the same result - {second_pipeline.result}") | |
print(second_pipeline) | |
if __name__ == "__main__": | |
writer_test() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment