foldLeft上的scala参数化类型
给定参数化方法的以下签名foldLeft上的scala参数化类型,scala,types,parameterized,foldleft,Scala,Types,Parameterized,Foldleft,给定参数化方法的以下签名 def double[A <: Byte](in:List[A]): List[A] = { //double the values of the list using foldLeft //for ex. something like: in.foldLeft(List[A]())((r,c) => (2*c) :: r).reverse //but it doesn't work! so.. } 但是,这会导致以下错误: $scala
def double[A <: Byte](in:List[A]): List[A] = {
//double the values of the list using foldLeft
//for ex. something like:
in.foldLeft(List[A]())((r,c) => (2*c) :: r).reverse
//but it doesn't work! so..
}
但是,这会导致以下错误:
$scala fold_ex.scala
error: overloaded method value * with alternatives:
(x: Double)Double <and>
(x: Float)Float <and>
(x: Long)Long <and>
(x: scala.Int)scala.Int <and>
(x: Char)scala.Int <and>
(x: Short)scala.Int <and>
(x: Byte)scala.Int
cannot be applied to (Int(in method plainDouble))
val k = 2*c
^
one error found
工程和输出:
val in = List(1,2,3,4,5)
println("in "+ in + " plainDouble ["+plainDouble(in)+"]")
是
如果我遗漏了一些非常明显的东西,我会道歉 问题是一种名称阴影:
def plainDouble[Int](in:List[Int]): List[Int] = {
^^^
// this is a type parameter called "Int"
您正在声明一个名为
Int
的类型变量,同时还试图使用具体的类型Int
,这会导致混淆。例如,如果删除类型变量(因为它没有实际使用)或将其重命名为I
,则代码将编译。@DNA是正确的,因为plainDouble[Int]
声明了一个名为Int
的类型参数,该参数与实际类型无关。因此,你试图使它非泛型实际上仍然是泛型的,但在某种程度上不是很明显
但是最初的问题呢
scala> def double[A <: Byte](in: List[A]): List[A] = in.foldLeft(List.empty[A])((r,c) => (2*c) :: r)
<console>:15: error: type mismatch;
found : x$1.type (with underlying type Int)
required: A
def double[A <: Byte](in: List[A]): List[A] = in.foldLeft(List.empty[A])((r,c) => (2*c) :: r).reverse
^
请注意,在转换为A
之前,我还必须调用toByte
。这并不是泛型工作的一个光辉例子,但关键是不兼容的返回类型导致了错误
另外,请注意,如果删除2*
,则不会出现这种情况:
def double[A <: Byte](in: List[A]): List[A] =
in.foldLeft(List.empty[A])((r,c) => c :: r).reverse
这依赖于一个隐式的Numeric[A]
可用于您的数值类型(在scala.math.Numeric
对象中,几乎可以用于您想要的任何数值类型)。它还依赖于从Int
到A
的隐式转换,因此我们可以编写A*2
。我们可以使用+
来取消此约束:
def double[A: Numeric](in: List[A]): List[A] = in.map(a => a + a)
是的,我也发现了。但是,如何使参数化类型工作呢?谢谢你的“DNA”和@m-z然而,
def doubleBound[A(2*c).toByte.asInstanceOf[A]::r.reverse val in=List(1,2,3,4,5)println(“in”+in+“doubleBound[“+doubleBound(in)+”])
仍然抱怨错误:推断类型参数[Int]不符合方法doubleBound的类型参数界限[A@cogitate AnInt
不是Byte
A
不能表示Int
,如果A
以Byte
为界,则A
不能表示Int
,如果A
以Byte
为界。请尝试使用Byte
的实际列表:列表(1,2
agree!!那么获取数字列表的泛型double应该是什么样的呢?@cogitate请看我的编辑。问题是scala中的数字类型并没有扩展除AnyVal
之外的普通类型。不过,您可能会感兴趣的是numeric
类型类。
scala> def double[A <: Byte](in: List[A]): List[A] = in.foldLeft(List.empty[A])((r,c) => (2*c) :: r)
<console>:15: error: type mismatch;
found : x$1.type (with underlying type Int)
required: A
def double[A <: Byte](in: List[A]): List[A] = in.foldLeft(List.empty[A])((r,c) => (2*c) :: r).reverse
^
def double[A <: Byte](in: List[A]): List[A] =
in.foldLeft(List.empty[A])((r,c) => (2*c).toByte.asInstanceOf[A] :: r).reverse
def double[A <: Byte](in: List[A]): List[A] =
in.foldLeft(List.empty[A])((r,c) => c :: r).reverse
import scala.math.Numeric.Implicits._
def double[A: Numeric](in: List[A])(implicit i2a: Int => A): List[A] =
in.map(_ * 2)
def double[A: Numeric](in: List[A]): List[A] = in.map(a => a + a)