def filter(self, filter_fn=None, desc=None, **kwargs):
        if filter_fn is not None and kwargs:
            raise TypeError('Must supply either a filter_fn or attribute filter parameters to filter(), but not both.')
        if filter_fn is None and not kwargs:
            raise TypeError('Must supply one of filter_fn or one or more attribute filter parameters to filter().')
        if desc is None:
            if filter_fn is not None:
                desc = getattr(filter_fn, '__name__', '')
            elif kwargs:
                desc = u", ".join([u"{}={!r}".format(key, value) for key, value in kwargs.items()])
        desc = u"filter({})".format(desc)
        if kwargs:
            def filter_fn(elem):
                return all(
                    getattr(elem, filter_key) == filter_value
                    for filter_key, filter_value
                    in kwargs.items()
                )
        return self.transform(lambda xs: (x for x in xs if filter_fn(x)), desc=desc)