Skip to content

Instantly share code, notes, and snippets.

@kendricktan
Last active April 11, 2019 06:26
Show Gist options
  • Select an option

  • Save kendricktan/bb0c8063a59dbcb2397ef8fe05195b88 to your computer and use it in GitHub Desktop.

Select an option

Save kendricktan/bb0c8063a59dbcb2397ef8fe05195b88 to your computer and use it in GitHub Desktop.
Maybe Monads in Python
from abc import ABC, abstractmethod
class Applicative(ABC):
@abstractmethod
def fmap(self, f):
raise Exception('Not implemented!')
class Functor(ABC):
@abstractmethod
def apply(self, f):
raise Exception('Not implemented!')
class Monad(ABC):
@abstractmethod
def bind(self, f):
raise Exception('Not implemented!')
# Maybe Monad
class Maybe(
Applicative,
Functor,
Monad
):
def __init__(self, value):
self.value = value
def bind(self, f):
"""
bind :: (a -> m b) -> m a -> m b
Param:
f :: (a -> m b)
"""
if self.value is None:
return Maybe(None)
value = self.value
return f(value)
def apply(self, ff):
"""
apply :: f (a -> b) -> f a -> f b
Param:
ff :: f (a -> b)
"""
f = ff.value
return self.fmap(f)
def fmap(self, f):
"""
fmap :: (a -> b) -> m a -> m b
Param:
f :: a -> b
"""
if self.value == None:
return Maybe(None)
new_value = f(self.value)
return Maybe(new_value)
def eval(self, v):
if callable(self.value):
return self.value(v)
return self.value
def __str__(self):
if self.value == None:
return 'Nothing'
return f'Just {self.value}'
def pure(v):
return Maybe(v)
def createMaybeInt(v):
if v < 0:
return pure(None)
return pure(v)
def minus(y): return lambda x: x - y
minusOne = minus(1)
minusTwo = minus(2)
def plus(y): return lambda x: x + y
plusOne = plus(1)
plusTwo = plus(2)
def noneIfLEZero(x): return pure(x) if x > 0 else pure(None)
# Just an Int
justAnInt = pure(42) \
.fmap(plus(10)) \
.bind(lambda x: pure (x + 1))
print(justAnInt)
# Produces Nothing
noneInt = pure(10) \
.fmap(minus(50)) \
.bind(noneIfLEZero)
print(noneInt)
# Still able to perform arbitrary logic
# Maybe monad without explicitly introducing
# it into the control flow
maybeNoneInt = pure(10) \
.fmap(minus(50)) \
.bind(noneIfLEZero) \
.fmap(plus(10))
print(maybeNoneInt)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment