It seems easy problem for any specific kind of Number i.e. Double/Integer but it is hard to write in general case.
implicit def iterebleWithAvg(data:Iterable[Double]) = new {
def avg:Double = data.sum / data.size
}
How to implement this for any kind of Number(Int,Float,Double,BigDecemial)?
Here's the way I define it in my code.
Instead of using
Numeric
, I useFractional
, sinceFractional
defines a division operation (Numeric
doesn't necessarily have division). This means that when you call.avg
, you will get back the same type you put in, instead of always gettingDouble
.I also define it over all
GenTraversableOnce
collections so that it works on, for example,Iterator
.Notice how if we give it a collection of
Double
, we get backDouble
and if we give itBigDecimal
, we get backBigDecimal
. We could even define our ownFractional
number type (which I do occasionally), and it will work for that.However,
Int
is not a kind ofFractional
, meaning that it doesn't make sense to get anInt
and the result of averagingInt
s, so we have to have a special case forInt
that converts to aDouble
.So averaging
Int
s gives us aDouble
:You have to pass an implicit
Numeric
which will allow summation and conversion to Double:The compiler will provide the correct instance for you:
You can the use the function to define an implicit view (provided you propagate the implicit numeric dependency):