Traverse/fold a nested case class in Scala without boilerplate code -


i have case classes mix of sum , product types:

sealed trait leaf case class goodleaf(value: int) extends leaf case object badleaf extends leaf  case class middle(left: leaf, right: leaf)  case class container(leaf: leaf)  case class top(middle : middle, container: container, extraleaves : list[leaf]) 

i want fold-like operations top structure. examples include:

  • count occurrences of badleaf
  • sum values in goodleafs

here code operations:

object top {   def fold[t](accu: t)(f : (t, leaf) => t)(top: top) = {     val allleaves =  top.container.leaf :: top.middle.left :: top.middle.right :: top.extraleaves     allleaves.foldleft(accu)(f)   }    private def countbadleaf(count: int, leaf : leaf) = leaf match {     case badleaf => count + 1     case _ => count   }    def countbad(top: top): int = fold(0)(countbadleaf)(top)    private def sumgoodleaf(count: int, leaf : leaf) = leaf match {     case goodleaf(v) => count + v     case _ => count   }    def sumgoodvalues(top: top) = fold(0)(sumgoodleaf)(top) } 

the real life structure dealing more complicated example made up. there techniques me avoid writing lots of boilerplate code?

i have cats library dependency, solution uses lib preferred. open including new dependencies in order solve problem.

for particular example, definition not recursive, i'd interested in seeing solution works recursive definitions also.

you create function returning leaves top, did allleaves, can work list[leaf] (with existing fold , other functions scala library, cats, etc provide).

for example :

def topleaves(top: top): list[leaf] =   top.container.leaf :: top.middle.left :: top.middle.right :: top.extraleaves  val isbadleaf: leaf => boolean = {   case badleaf => true   case _       => false }  val leafvalue: leaf => int = {   case goodleaf(v) => v   case _           => 0 } 

which use as

import cats.implicits._ // or // import cats.instances.int._ // import cats.instances.list._ // import cats.syntax.foldable._  val leaves = topleaves(sometop)  val badcount   = leaves.count(isbadleaf) val badandgood = leaves.partition(isbadleaf) // (list[leaf], list[leaf]) val sumleaves  = leaves.foldmap(leafvalue) 

i not sure if helps actual use case ? in general heterogeneous structure (like top) want convert somehow more homogeneous (like list[leaf] or tree[leaf]) can fold over.

if have recursive structure @ talks recursion schemes (with matryoshka library in scala).


Comments

Popular posts from this blog

sql server - Cannot query correctly (MSSQL - PHP - JSON) -

php - trouble displaying mysqli database results in correct order -

C++ Linked List -