Props: Gen a, thunks, and closures

February 20, 2014

In my previous post about Props, I said I would elaborate on its equivalent to Gen a from Haskell’s QuickCheck.

In Haskell, consider the following implementation of a tree:

data Tree a = Tree { value :: a
                   , children :: [Tree a]
                   } deriving (Eq, Show)

Let’s make it an instance of Arbitrary1:

instance (Arbitrary a) => Arbitrary (Tree a) where
    arbitrary = do value <- arbitrary
                   children <- arbitrary
                   return Tree { value=value
                               , children=children

Since Haskell can determine types at compile time, we don’t need to put in any type annotations. In particular, we don’t need to tell arbitrary what type we want it to return when making the arbitrary value and children.

In Python, the following class which implements ArbitraryInterface, would be approximately2 equivalent to the above Haskell type3:

class Tree(ArbitraryInterface):
    value = None
    children = []

    def __init__(self, value, children):
        self.value = value
        self.children = children

    def arbitrary(cls):
        return cls(
            arbitrary(int),           # Value
            arbitrary(list_of(Tree))  # Children

Ignoring some details4, we can think of Haskell’s Gen a as representing something which can be turned into an a. How can we make something that can be turned into an a? We can use a thunk! A thunk is an object which represents a paused computation. Forcing a thunk causes the computation to occur. Since Haskell is lazy, everything is thunk by default. In Python, iterators can be thought of as lazy, but they usually represent collections of objects, rather than just a single object, so this would not be the best use of iterators.

One simple way to implement a thunk is to make a closure which takes no arguments. For example:

def setup_a_thunk(some, variables, _for, our, computation):
    def thunked_computation():
        // ...
        // Do a bunch of work
        // Using the variables passed in to setup_a_thunk
        return a_result
    return thunked_computation

We can then call setup_a_thunk a bunch of times, but it would not actually do the work until we force it, i.e. call the thunk with no arguments:

a_thunk = setup_a_thunk(...)
another_thunk = setup_a_thunk(...)

one_result = a_thunk()  # This forces the thunk.

Since objects are closures, we can view the class definition for Tree as setting up a closure, which we force when we call arbitrary.

So, there you have it. The equivalent of Haskell QuickCheck’s Gen a in Props is a closure!

  1. This won’t terminate as it would create an infinite Tree structure! But that’s not important here. See StackOverflow if you want a version that would terminate.

  2. The Python Tree class is just for int. This would be equivalent to the Tree Int type in Haskell. If we had generics in Python… something for a later post.

  3. This also won’t terminate. I’ll leave that as an exercise for the reader.

  4. For example, Haskell’s QuickCheck passes in a nonce to Gen a to make sure the generated a is unique. There’s also the notion of shrink which Props does nothing with. Yet.