Scala:通用加权平均函数
我想实现一个通用加权平均函数,它放宽了对值的要求,并且权重属于同一类型.即,我想支持以下序列:(值:Float,weight:Int)和(value:Int,weight:Float)参数,而不仅仅是:(值:Int,weight:Int). [在此之前见到我之前的
question.]
这就是我目前所拥有的: def weightedSum[A: Numeric](weightedValues: GenSeq[(A,A)]): (A,A) def weightedAverage[A: Numeric](weightedValues: GenSeq[(A,A)]): A = { val (weightSum,weightedValueSum) = weightedSum(weightedValues) implicitly[Numeric[A]] match { case num: Fractional[A] => ... case num: Integral[A] => ... case _ => sys.error("Undivisable numeric!") } } 如果我喂它,例如: val values:Seq[(Float,Float)] = List((1,2f),(1,3f)) val avg= weightedAverage(values) 但是,如果我不“重叠”从Int到Float的权重: val values= List((1,3f)) //scalac sees it as Seq[(Int,Float)] val avg= weightedAverage(values) Scala编译器会告诉我:
有办法绕过这个吗? 我尝试编写一个NumericCombine类,我用A和B参数化,将类型“组合”成“常见”类型AB(例如,组合Float和Int给你Float): abstract class NumericCombine[A: Numeric,B: Numeric] { type AB <: AnyVal def fromA(x: A): AB def fromB(y: B): AB val num: Numeric[AB] def plus(x: A,y: B): AB = num.plus(fromA(x),fromB(y)) def minus(x: A,y: B): AB = num.minus(fromA(x),fromB(y)) def times(x: A,y: B): AB = num.times(fromA(x),fromB(y)) } 我设法用类型类模式编写基于此的简单时间和函数,但由于NumericCombine引入了路径依赖类型AB,因此“组合”类型证明比我预期的更难.有关更多信息,请参阅this问题,有关NumericCombine的完整实施,请参阅here. 更新 作为another question(完整工作演示here)的答案,已经获得了一个令人满意的解决方案,但是考虑到discussion中@ziggystar提出的要点,仍然有一些设计改进的空间. 解决方法
线性组合
我认为涉及通过类型S的标量对T类型的某些元素进行称重/缩放的更一般的任务是线性组合.以下是某些任务的权重约束: > linear combination:没有限制 因此,根据该分类的最一般情况是线性组合. 编辑:您对类型的最常见要求是T在环S上形成module (wiki),或者T是S模块. 尖塔 您可以使用类型类来设置这些要求.还有spire,已经有Field和VectorSpace的类型类.我自己从未使用过它,所以你必须自己检查一下. Float / Int不起作用 从这个讨论中可以看出,以及你已经观察到的是,将Float作为权重,而Int作为元素类型将无法解决,因为整数不会在实数上形成向量空间.你必须首先将Int推广到Float. 通过类型类推广 标量类型只有两个主要候选者,即Float和Double. case class Promotable[R,T](promote: R => T) object Promotable { implicit val intToFloat = Promotable[Int,Float](_.toFloat) implicit val floatToDouble = Promotable[Float,Double](_.toDouble) implicit val intToDouble = Promotable[Int,Double](_.toDouble) implicit def identityInst[A] = Promotable[A,A](identity) }As a "small" solution you could write a typeclass def weightedAverage[S,VS](values: Seq[(S,VS)])(implicit p: Promotable[VS,S]) = ??? (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |