Combines the partial order with either (1) a value in the partial 
        order's domain, or (2) another partial order with the same domain.

        When combining with a value, an optional `is_positive` parameter can
        be set to False, meaning that the merged value should be excluded.

def merge(self, other, is_positive=True):
        """ Combines the partial order with either (1) a value in the partial 
        order's domain, or (2) another partial order with the same domain.

        When combining with a value, an optional `is_positive` parameter can
        be set to False, meaning that the merged value should be excluded.
        """
        other = self.coerce(other, is_positive)
        # the above coercion forces equal domains, and raises an 
        # exception otherwise
        if self.is_equal(other):
            pass
        elif other.is_entailed_by(self):
            # this is the case where the other contains all of the values
            # we have and more, so we don't gain anything by keeping it around
            pass  # do nothing
        elif self.is_entailed_by(other):
            # TODO: what if other has a size of 0, do we still merge?
            # replace self with other
            self.lower = other.lower
            self.upper = other.upper
            self.__values_computed = False
            return self
        elif self.is_contradictory(other):
            raise Contradiction("Cannot merge partial orders")
        else:
            # merge the two
            def add_single_value(val, is_positive):
                if not is_positive:
                    # lower generalization boundaries
                    # replace val with its parents
                    if not val in self.lower:
                        self.lower.add(val)
                        self.__values_computed = False        
                else:
                    # raise specialization boundaries
                    if not val in self.upper:
                        self.upper.add(val)
                        self.__values_computed = False

            for general in other.upper:
                add_single_value(general, True)
            for specific in other.lower:
                add_single_value(specific, False)

        if len(self) == 0:
            raise Contradiction("Partial Ordering has No Members")
            
        return self