[英]scala parameterized type on 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..
}
在解決參數化類型的foldLeft之前,我嘗試獲取以下內容
def plainDouble[Int](in:List[Int]): List[Int] = {
in.foldLeft(List[Int]())((r:List[Int], c:Int) => {
var k = 2*c
println("r is ["+r+"], c is ["+c+"]")
//want to prepend to list r
// k :: r
r
})
}
但是,這導致以下錯誤:
$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
如果我將def的簽名更改為以下內容:
def plainDouble(in:List[Int]): List[Int] = { ...}
的作品和輸出為:
val in = List(1,2,3,4,5)
println("in "+ in + " plainDouble ["+plainDouble(in)+"]")
是
in List(1, 2, 3, 4, 5) plainDouble [List(2, 4, 6, 8, 10)]
抱歉,如果我錯過了一些非常明顯的內容。
問題是一種名稱隱藏:
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
^
這里的問題是2 * c
是一個Int
,而不是A
Int
上的*(byte: Byte)
方法返回另一個Int
。 因此,消息(with underlying type Int)
。 請注意,如果強制轉換為A
,它將編譯:
def double[A <: Byte](in: List[A]): List[A] =
in.foldLeft(List.empty[A])((r,c) => (2*c).toByte.asInstanceOf[A] :: 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
特征。
import scala.math.Numeric.Implicits._
def double[A: Numeric](in: List[A])(implicit i2a: Int => A): List[A] =
in.map(_ * 2)
這依賴於隱式的Numeric[A]
可用於您的數字類型( scala.math.Numeric
對象中存在該scala.math.Numeric
,幾乎是您想要的任何數字類型)。 它還依賴於從Int
到A
的隱式轉換,以便我們可以編寫a * 2
。 我們可以使用+
代替此約束:
def double[A: Numeric](in: List[A]): List[A] = in.map(a => a + a)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.