Reduce function on custom data structure using Cats Semigroup
Yes, using a Monoid can simplify what you want:

def foldMonoidal[A : Monoid](f: Element =&gt; A): A =
      Monoid.combine(f(this), Monoid.combineAll(els.map(f)))
...

e1.foldMonoidal(_.value)


One issue with that though is that you lose the information of the nested structure: You may as well have just a list of (name, value).

Any nested data structure can have a fold operation defined for it, in a way that keeps knowledge of its structure. In your case, this would be:

def fold[A](f: (Element, List[A]) =&gt; A): A =
  f(this, els.map(_.fold(f)))
...
e1.fold[Int]((el, list) =&gt; el.value + list.sum)


You can see this allows more freedom, e.g. you may want to sum the value with the average of the nested elements, which you couldn't do with the monoidal solution above.

e1.fold[Double]((el, list) =&gt; el.value + list.sum / list.size)


Or for pretty-printing:

e1.fold[String]((el, strEls) =&gt; s"(${el.name} -&gt; ${el.value}, ${strEls.mkString("[", ",", "]")}")
// (Zero -&gt; 0, [(One -&gt; 1, [(Two -&gt; 2, [(Three -&gt; 3, [],(Four -&gt; 4, []]],(Five -&gt; 5, [(Six -&gt; 6, [],(Seven -&gt; 7, [],(Eight -&gt; 8, [(Nine -&gt; 9, [],(Ten -&gt; 10, []]]]