I am trying to write a general weighted average function. I want to relax the requirements for values and weights of the same type. those. I want to support word sequences: (value:Float,weight:Int) and (value:Int,weight:Float) arguments, and not just: (value:Int,weight:Int)
To do this, I first need to implement a function that takes two common numerical values and returns their product.
def times[A: Numeric, B: Numeric](x: B, y: A): (A, B) : ??? = {...}
Writing down the signature and thinking about the return type, I realized that I needed to define some kind of hierarchy for Numerics to determine the return type. those. x:Float*y:Int=z:Float , x:Float*y:Double=z:Double .
Now the number class defines operations plus , times , etc. only for arguments of the same type. I think I will need to implement a type:
class NumericConverter[Numeirc[A],Numeric[B]]{ type BiggerType=??? }
so that I can write my time function as:
def times[A: Numeric, B: Numeric](x: B, y: A): (A, B) : NumericConverter[Numeirc[A],Numeric[B]].BiggerType= {...}
and convert the "smaller type" to "large" and pass it to times() .
Am I on the right track? How do I "implement" BiggerType ?
clear i can't do something like:
type myType = if(...) Int else Float
as it is being evaluated dynamically, therefore it does not work.
I understand that I could do this. Using Scalaz, etc., but this is an academic exercise, and I want to understand how to write a function that statically returns a type based on argument types .
Feel free to let me know if there is an even easier way to do this.
Update
that's what i came up with.
abstract class NumericsConvert[A: Numeric,B: Numeric]{ def AisBiggerThanB: Boolean def timesA=new PartialFunction[(A,B), A] { override def isDefinedAt(x: (A, B)): Boolean = AisBiggerThanB override def apply(x: (A, B)): A = implicitly[Numeric[A]].times(x._1, x._2.asInstanceOf[A]) } def timesB=new PartialFunction[(A,B), B] { override def isDefinedAt(x: (A, B)): Boolean = !AisBiggerThanB override def apply(x: (A, B)): B = implicitly[Numeric[B]].times(x._1.asInstanceOf[B], x._2) } def times: PartialFunction[(A, B), Any] = timesA orElse timesB } def times[A: Numeric, B: Numeric](x: B, y: A)= implicitly[NumericsConvert[A,B]].times(x,y)
which is stupid since I have to create implications for
IntDouble extends NumericsConvert[Int,Double]
and
DoubleInt extends NumericsConvert[Double,Int]
not to mention that the return type of times now Any , but independently, I get errors for my time functions. I thought I would add it here if this helps in solving the problem. so the side question: how can I pass context-related types of one class / function to another, as I try to do at times .