Skip to content

Instantly share code, notes, and snippets.

@stojan211287
Last active May 26, 2019 21:26
Show Gist options
  • Save stojan211287/05f0a3cc1f5531488d5d8c32ffd7d285 to your computer and use it in GitHub Desktop.
Save stojan211287/05f0a3cc1f5531488d5d8c32ffd7d285 to your computer and use it in GitHub Desktop.
Simple Writer monad demo in Python3
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)
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