def fold_spaces(low_spaces, high_spaces):
    """
    Creates all possible combinations of hyperspaces.

    Parameters
    ----------
    * `low_spaces` [list, shape=(n_spaces,)]:
        lower spaces defined by hyperspace classes.

    * `high_spaces` [list, shape=(n_spaces,)]:
        lower spaces defined by hyperspace classes.

    Returns
    -------
    * `hyperspace` [`list of lists`, shape=(2**n_spaces, n_spaces)]:
        - All combinations of hyperspaces. Each list within hyperspace
          is a search space to be distributed across 2**n_spaces nodes.
    """
    if len(low_spaces)  != len(high_spaces):
        raise ValueError(("low_spaces and high_spaces must have the same length. "
                         "Got {} and {} respectively.".format(len(low_spaces), len(high_spaces))))

    indices = len(low_spaces)
    num_hyperspaces = 2**indices
    hyperspace = [[] for i in range(num_hyperspaces)]

    for space in range(num_hyperspaces):
        for index in range(indices):
            bit_tester = 1 << index
            if space & bit_tester:
                hyperspace[space].insert(index, low_spaces[index])
            else:
                hyperspace[space].insert(index, high_spaces[index])

    return hyperspace