docs: def aggregate(self, func, seed=None):
          """
          Perform a calculation over a given enumerable using the initial seed
          value
          :param func: calculation to perform over every the enumerable.
          This function will ingest (aggregate_result, next element) as parameters
          :param seed: initial seed value for the calculation. If None, then the
          first element is used as the seed
          :return: result of the calculation
          """
          if self.count() == 0:
              raise NoElementsError("No elements perform aggregation")
          result = seed if seed is not None else self.first()
          for i, e in enumerate(self):
              if i == 0 and seed is None:
                  continue
              result = func(result, e)
          return result