So, I have been trying to wrap my mind around Functors, Applicatives and Monads lately. In my understanding such a design pattern allows one to separate "pure functions" from "impure" ones and ensure that there is no branching out and calling different functions from a given function and cause side effects.
So, let's say I have a dictionary and want to apply/compose some functions over it.
input = {"x": 2, "y": 5, "out": None}
def f(x):
return x + 2
def g(y):
return y - 3
def h(x, y):
return x * y
class Functor:
def __init__(self, input):
self.input = input
def fmap(self, function):
val = self.input
if function.__name__ == "f":
val["x"] = function(val["x"])
elif function.__name__ == "g":
val["y"] = function(val["y"])
elif function.__name__ == "h":
val["out"] = function(val["x"], val["y"])
elif function.__name__ == "print":
function(val)
else:
print("fmap not defined for this function!")
return Functor(val)
def __rshift__(self, function):
return self.fmap(function)
Functor(input) >> f >> g >> h >> print #results in {"x": 4, "y": 2, "out": 8}
Functor(input) >> h >> g >> h >> print #results in {"x": 2, "y": 2, "out": 4}
Functor(input) >> g >> f >> h >> print #results in {"x": 4, "y": 2, "out": 8}
So, is my understanding of functors correct? If yes, is this the way one implements the fmap, or do you create a wrapper around each function so as to define the fmap inside the respective wrapper or what? And, is this the way to keep track of the state of inputs, post function application?