Skip to content

Instantly share code, notes, and snippets.

@chewxy
Created August 7, 2015 00:08
Show Gist options
  • Save chewxy/66bcae134ae743f5bff8 to your computer and use it in GitHub Desktop.
Save chewxy/66bcae134ae743f5bff8 to your computer and use it in GitHub Desktop.
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