ShS*_*ShS 7 generics scala numeric implicit
我正在尝试编写通用的加权平均函数.我想放宽对值和重量相同类型的要求.即,我想支持说:(value:Float,weight:Int)和(value:Int,weight:Float)参数的序列而不仅仅是:(value:Int,weight:Int)
为此,我首先需要实现一个带有两个通用数值并返回其产品的函数.
def times[A: Numeric, B: Numeric](x: B, y: A): (A, B) : ??? = {...}
Run Code Online (Sandbox Code Playgroud)
编写签名并考虑返回类型,让我意识到我需要为Numerics定义某种层次结构来确定返回类型.即x:Float*y:Int=z:Float,x:Float*y:Double=z:Double.
现在,数字类定义操作plus,times等只为同一类型的参数.我想我需要实现一个类型:
class NumericConverter[Numeirc[A],Numeric[B]]{
type BiggerType=???
}
Run Code Online (Sandbox Code Playgroud)
这样我就可以把我的时间函数写成:
def times[A: Numeric, B: Numeric](x: B, y: A): (A, B) :
NumericConverter[Numeirc[A],Numeric[B]].BiggerType= {...}
Run Code Online (Sandbox Code Playgroud)
并将"较小的类型"转换为"较大的类型"并将其转换为times().
我是在正确的轨道上吗?我将如何"实施" BiggerType?
显然我做不了类似的事情:
type myType = if(...) Int else Float
Run Code Online (Sandbox Code Playgroud)
因为它是动态评估的,所以它不起作用.
我知道我可以使用Scalaz等来做这个,但这是一个学术练习,我想了解如何编写一个静态返回基于参数类型的类型的函数.
如果有更简单的方法,请随时告诉我.
更新:
这就是我想出来的.
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)
Run Code Online (Sandbox Code Playgroud)
这是愚蠢的,因为我将不得不为两者创造暗示
IntDouble extends NumericsConvert[Int,Double]
Run Code Online (Sandbox Code Playgroud)
和
DoubleInt extends NumericsConvert[Double,Int]
Run Code Online (Sandbox Code Playgroud)
更不用说的返回类型times是现在Any,但无论如何,我得到错误我的时间的功能.我想我会在这里添加它,以防它可能有助于达成解决方案.所以侧面问题:我如何能够将一个类/函数的上下文绑定类型传递给另一个类/函数,就像我想要的那样.
我认为你正在努力实现这一目标.
你需要两个参数都是"证据" Numeric.有了这个,就让证据完成工作.Scala将采用数字扩展,以便结果是两种接收类型中更一般的.
def mult[T](a: T, b: T)(implicit ev:Numeric[T]): T =
ev.times(a,b)
Run Code Online (Sandbox Code Playgroud)
如果你想获得一点点发烧友,你可以获得所需的暗示.然后它更容易阅读和理解.
def mult[T: Numeric](a: T, b: T): T = {
import Numeric.Implicits._
a * b
}
Run Code Online (Sandbox Code Playgroud)
证明:
mult(2.3f , 7) //res0: Float = 16.1
mult(8, 2.1) //res1: Double = 16.8
mult(3, 2) //res2: Int = 6
Run Code Online (Sandbox Code Playgroud)
有关泛型类型和数字扩展的更多信息,这个问题及其答案值得研究.
| 归档时间: |
|
| 查看次数: |
751 次 |
| 最近记录: |