Q:

Scala multivariate array sum

I am calculating confidence interval of some ratios using bootstrapping for multi variables, and each variable has different confidence intervals. 
case class Limits(lowerLimit: Double, upperLimit: Double, confidenceInterval: Double)

case class CI(c85: Limits, c90: Limits, c95: Limits, c99: Limits)

For bootstrapping, I am running a loop for 100 times.
val arrCIRatio: Array[CI] = Array()
var ci85: Limits = new Limits(0.0, 0.0, 0.0)
var ci90: Limits = new Limits(0.0, 0.0, 0.0)
var ci95: Limits = new Limits(0.0, 0.0, 0.0)
var ci99: Limits = new Limits(0.0, 0.0, 0.0)

val a = Array(1,2,3,4,5,6,7,8,9,10)
val rg = new scala.util.Random(100)

 for(iteration <- 1 to 100){
    val i= rg.nextInt(10)      
    ci85 = getInterval(a(i), 0.85)
    ci90 = getInterval(a(i), 0.90)
    ci95 = getInterval(a(i), 0.95)
    ci99 = getInterval(a(i), 0.99)

    arrCIRatio(iteration) = new CI(ci85,ci90,ci95,ci99)
}

After the loop finishes, I would like to take average of each upper and lower limits inside the CI array for all the ci85, ci89, ci95, ci99.
I can use foldLeft to calculate the sum
x.foldLeft(0.0)( (x, y) => x + y.lowerLimit, x.foldLeft(0.0)( (x, y) => x + y.upperLimit

or in naive way:
var avgci85: Limits = new Limits(0.0, 0.0, 0.0)
var avgci90: Limits = new Limits(0.0, 0.0, 0.0)
var avgci95: Limits = new Limits(0.0, 0.0, 0.0)
var avgci99: Limits = new Limits(0.0, 0.0, 0.0)

 for(ci <- arrCIRatio){  
    ci85 = ci.c85
    ci90 = ci.c90
    ci95 = ci.c95
    ci99 = ci.c99

    avgci85 = new Limits(avgci85.lowerLimit + ci85.lowerLimit, avgci85.upperLimit + ci85.upperLimit, 0.85) 
    avgci90 = new Limits(avgci90.lowerLimit + ci90.lowerLimit, avgci90.upperLimit + ci85.upperLimit, 0.90) 
    avgci95 = new Limits(avgci95.lowerLimit + ci95.lowerLimit, avgci95.upperLimit + ci85.upperLimit, 0.95) 
    avgci99 = new Limits(avgci99.lowerLimit + ci99.lowerLimit, avgci99.upperLimit + ci85.upperLimit, 0.99) 
}

But I have to do the same process for atleast 10 variables, and all the CI inside the array.
So in the end, for 1 variable it will be a 3 dimensional array of 10000 x 4 x 3.
I don't know how to sum all the variables inside that array e.g. summing all the lower limit of ci85 in the array. It would be great if someone can help with it.

A:

Maybe just create method/operator for your CI and Limits which would allow you to combine two instances? Something like that:
case class Limits(lowerLimit: Double, upperLimit: Double, confidenceInterval: Double) {
  // operator |+| would allow us to combine two limits
  def |+|(l: Limits): Limits = Limits(l.lowerLimit + lowerLimit, l.upperLimit + upperLimit, confidenceInterval)
 // I don't know what should be done in case of attempt of combining two limits with different confidenceInterval. 
 // Maybe it's a sign that every kind of Limits should be separate case class extending the common trait
}

object Limits {
  val Zero = new Limits(0,0,0) //zero element for convienience
}

case class CI(c85: Limits, c90: Limits, c95: Limits, c99: Limits) {
  //same operator for CI, we use |+| from Limits to combine them
  def |+|(c: CI): CI = CI(c.c85 |+| c85, c.c90 |+| c90, c.c95 |+| c95, c.c99 |+| c99)
}

object CI {
  val Zero = new CI(Limits.Zero, Limits.Zero, Limits.Zero, Limits.Zero)
}

Then you'd be able to fold your CI easily:
arrCIRatio.fold(CI.Zero)(_ |+| _)

What we did is called monoid. Instead of implementing |+| and Zero inside cases classes you could implement it using typeclasses (as described in the article).

