我正在尝试创建超类实例的映射器并将其传递给父类型的集合:
def numberToString = (n:Number) => n.toString()
List(1.1, 2.1, 3.1).map(numberToString)
错误:
type mismatch; found : Number => String required: Double => ?
我很惊讶Scala中的map方法不允许超类型的函数。有更好的方法吗?
答案 0 :(得分:2)
Scala中没有Number
类型,所以我猜你的意思是Numeric
(Double
不是Numeric
的子类,但它可以是通过隐式转换强制转换为Numeric
。
如果是这样,您可以通过将Numeric
指定为numberToString
函数的参数的上下文绑定来实现您想要的目标(即,指定必须存在范围内的隐式转换)参数类型为Numeric
,通常适用于Int
,Double
等):
scala> def numberToString[N : Numeric] = (n: N) => n.toString()
numberToString: [N](implicit evidence$1: Numeric[N])N => String
scala> List(1.1, 2.1, 3.1).map(numberToString2)
res2: List[String] = List(1.1, 2.1, 3.1)
修改强>
请注意,我假设您希望尽可能多地保留Scala世界。如果您打算将参数限制为numberToString
到java.lang.Number
类型而不是scala.math.Numeric
,那么请使用@wingedsubmariner给出的类似视图边界符号。
答案 1 :(得分:1)
Scala允许您将接受超类型的函数传递给map
。这实际上是通过向上转换序列来实现的,而不是按原样接受函数:
def intSeqToInt(x: Seq[Int]) = x.length
List(List(1), List(2)).map(intSeqToInt)
res2: List[Int] = List(1, 1)
List [List [Int]]被强制转换为List [Seq [Int]],然后其map
具有intSeqToInt
的正确类型。
你的问题是Double不是Number的子类。 Number是指java.lang.Number,Double是scala.Double,它只是AnyVal的一个子类。存在从Double到Number的隐式转换,但在这种情况下,您必须使用视图绑定专门请求它:
def numberToString[N <% Number](n:N) = n.toString()
List(1.1, 2.1, 3.1).map(numberToString[Double])
答案 2 :(得分:0)
允许使用超级类型,但... Number
为java.lang.Number
,不是scala.Double
的超级类型。
具有实际超类型的示例:
scala> def numberToString = (n:AnyVal) => n.toString()
numberToString: AnyVal => String
scala> List(1.1, 2.1, 3.1).map(numberToString)
res0: List[String] = List(1.1, 2.1, 3.1)
显然你可以在这里使用_.toString
,但我想这只是你问题的简化版本。
编辑:在数值的特殊情况下,正确的方法是在@ Shadowlands的答案中使用Numeric
。