Home > Back-end >  how to aggregate case-class in scala gracefully?
how to aggregate case-class in scala gracefully?

Time:05-24

case class value(x1:Long, x2: Double, ..., xk: Long, ... ,xn:Int) {

  def add(rValue: Value): Value = {
   Value(
     x1 = x1   rValue.x1,
     ...
     xk = xk   rValue.xk,
     ...
     xn = xn   rvalu.xn
   )
 }

}

I want to aggregate case-class('value'), I think this manual implementation is not elegant when n is large (such as n = 500?)

CodePudding user response:

Fields in case classes are immutable, return a new instance with all the updated fields.

case class Value(x: Int, y: Int) { 
  def   (other: Value): Value =
    Value(x   other.x, y   other.y)
}

Value(10, 20)   Value(10, 20)
//res0: Value = Value(20,40)

Value(10, 20)   Value(20, 30)   Value(30, 50)
//res1: Value = Value(60,100)

CodePudding user response:

Here is a solution works in Scala3 with build-in api only:

trait Add[N] { def add(x: N, y: N): N }

object Add:
  import scala.deriving.Mirror.ProductOf
  
  given Add[Int]        = _   _
  given Add[Long]       = _   _
  given Add[Float]      = _   _
  given Add[Double]     = _   _
  given Add[EmptyTuple] = (_, _) => EmptyTuple
  given [H, T <: Tuple](using ha: Add[H], ta: Add[T]): Add[H *: T] = 
    case (hx*:tx, hy*:ty) => ha.add(hx, hy) *: ta.add(tx, ty)
  given [P <: Product](using p: ProductOf[P], a: Add[p.MirroredElemTypes]): Add[P] = 
    (x, y) => p.fromProduct(a.add(Tuple.fromProductTyped(x), Tuple.fromProductTyped(y)))
  

Then we can define Value class as:

scala> case class Value(x1: Int, x2: Float, x3: Double):
     |   def add(that: Value): Value = summon[Add[Value]].add(this, that)
     |

scala> Value(1, 2, 3).add(Value(3, 4, 5))
val res0: Value = Value(4,6.0,8.0)
  • Related