Created
August 7, 2015 00:08
-
-
Save chewxy/66bcae134ae743f5bff8 to your computer and use it in GitHub Desktop.
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 math | |
class Monad(object): | |
__slots__=['value'] | |
def bind(self, f): | |
if type(self) is List and type(self.value) is list: | |
return self._bind(f) | |
elif type(self) is Value and type(self.value) is list: | |
# transform it into a List(Value) | |
self.toListOfValues() | |
newSelf = List(self.value) | |
return newSelf._bind(f) | |
else: | |
return self._bind(f) | |
def toListOfValues(self): | |
if type(self.value) is list: | |
for i, v in enumerate(self.value): | |
self.value[i] = Value(v) | |
class Value(Monad): | |
__slots__=['value'] | |
def __init__(self, v=None): | |
if type(v) is Value: | |
self.value = v.value | |
else: | |
self.value = v | |
def _bind(self, f): | |
if self.value is None: | |
return Value(None) | |
return Value(f(self.value)) | |
def __repr__(self): | |
if self.value is None: | |
return "Nothing" | |
return "Just {}".format(self.value) | |
class List(Monad): | |
__slots__=['value'] | |
def __init__(self, v): | |
if type(v) is list: | |
self.value = v | |
elif type(v) is tuple: | |
self.value = list(v) | |
else: | |
self.value = [v] | |
def _bind(self, f): | |
l = [] | |
for v in self.value: | |
try: | |
res = v.bind(f) | |
except AttributeError: # bind doesn't exist, then apply directly | |
res = f(v) | |
# flatten | |
if type(res) is Value: | |
res.toListOfValues() | |
try: | |
for r in res.value: | |
l.append(r) | |
except TypeError: | |
l.append(res) | |
return List(l) | |
def __repr__(self): | |
return "[" + \ | |
",".join("{}".format(i) for i in self.value) + \ | |
"]" | |
def div(num, denom): | |
try: | |
return num/denom | |
except ZeroDivisionError: | |
return None | |
def sqrt(x): | |
if x < 0: | |
return None | |
s = math.sqrt(x) | |
return [s, -s] | |
def curriedDiv(num): | |
def shouldBeLambda(denom): | |
return div(num, denom) | |
return shouldBeLambda | |
x = Value(100) | |
f = curriedDiv(200) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment