Skip to content

Instantly share code, notes, and snippets.

@nvanderw
Created August 21, 2012 07:19
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nvanderw/3413049 to your computer and use it in GitHub Desktop.
Save nvanderw/3413049 to your computer and use it in GitHub Desktop.
Typeclass stuff in Python
import itertools
# Monad instance on a Python iterator, very similar to Haskell's list monad.
# In general, Haskell typeclass instances can be regarded as dictionaries which
# map the implemented function to its implementation. For a good explanation of
# this, see Philip Wadler's "Faith, Evolution, and Programming Languages"
# lecture. What this means for us is that we can write a function whose type
# signature in Haskell would be:
# Monad m => f m
#
# Where f m is some type parameterized over m, as:
# Monad m -> f m
#
# That is, the instance of monad is passed as a dictionary along with the
# function parameterized over the monad. This IterMonad class is an example of
# such a dictionary.
#
# We can see a dynamic type system as having a single type: Dyn. Thus the
# category of Python types has a single object and is defined entirely by its
# morphisms.
class IterMonad(object):
# Functor implementation
@staticmethod
def fmap(f, m): return itertools.imap(f, m)
# Monad implementation
@staticmethod
def inject(a): return [a]
@staticmethod
def join(m): return itertools.chain.from_iterable(m)
# Monoid/MonadPlus implementation
mzero = []
@staticmethod
def mplus(m, n):
return itertools.chain(m, n)
# Given a monad instance like above, yields a class object with a couple utility
# functions for monads.
def getMonadUtils(inst):
class MonadUtils(object):
@staticmethod
def bind(m, f):
return inst.join(inst.fmap(f, m))
# mapM, liftM, and all that goodness goes here
# Monadic filter example
@staticmethod
def mfilter(p, m):
return MonadUtils.bind(m, lambda a: inst.inject(a) if p(a) else inst.mzero)
return MonadUtils
# Implementation of IO Monad goes here
# Filter out odd elements from [0..]
for elem in getMonadUtils(IterMonad).mfilter(lambda n: (n % 2) == 0, itertools.count()):
print elem
@ksheedlo
Copy link

It's pretty trivial to enforce type schema on Python objects. We did this a lot at TiVo. Define a schema in one place, along with a checking function. Then you can require DTOs or more general objects to have certain members that could recursively have types enforced on them. It might be a more pythonic way to do this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment