docs: def inverse(val: Any, default: Any = RaiseTypeErrorIfNotProvided) -> Any:
      """Returns the inverse `val**-1` of the given value, if defined.
  
      An object can define an inverse by defining a __pow__(self, exponent) method
      that returns something besides NotImplemented when given the exponent -1.
      The inverse of iterables is by default defined to be the iterable's items,
      each inverted, in reverse order.
  
      Args:
          val: The value (or iterable of invertible values) to invert.
          default: Determines the fallback behavior when `val` doesn't have
              an inverse defined. If `default` is not set, a TypeError is raised.
              If `default` is set to a value, that value is returned.
  
      Returns:
          If `val` has a __pow__ method that returns something besides
          NotImplemented when given an exponent of -1, that result is returned.
          Otherwise, if `val` is iterable, the result is a tuple with the same
          items as `val` but in reverse order and with each item inverted.
          Otherwise, if a `default` argument was specified, it is returned.
  
      Raises:
          TypeError: `val` doesn't have a __pow__ method, or that method returned
              NotImplemented when given -1. Furthermore `val` isn't an
              iterable containing invertible items. Also, no `default` argument
              was specified.
      """
      from cirq import ops  # HACK: avoid circular import
  
      # Check if object defines an inverse via __pow__.
      raiser = getattr(val, '__pow__', None)
      result = NotImplemented if raiser is None else raiser(-1)
      if result is not NotImplemented:
          return result
  
      # Maybe it's an iterable of invertible items?
      # Note: we avoid str because 'a'[0] == 'a', which creates an infinite loop.
      if (isinstance(val, collections.Iterable) and
              not isinstance(val, (str, ops.Operation))):
          unique_indicator = []  # type: List[Any]
          results = tuple(inverse(e, unique_indicator) for e in val)
          if all(e is not unique_indicator for e in results):
              return results[::-1]
  
      # Can't invert.
      if default is not RaiseTypeErrorIfNotProvided:
          return default
      raise TypeError(
          "object of type '{}' isn't invertible. "
          "It has no __pow__ method (or the method returned NotImplemented) "
          "and it isn't an iterable of invertible objects.".format(type(val)))