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 An
Int
不是
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)