2013-09-30 74 views
0

爲了獲得更多有關Scala的經驗,作爲一個實驗,我實現了一個具有類似List的API的類,但實現爲包含第一個元素的索引的IndexedSeq列表; tail僅返回與遞增索引的副本,並在前面加上Array s是O(1),而追加Array s是O(M)中,m =列表< =元素的數目的長度。Scala:類型不匹配,返回BlockList [Any]而不是BlockList [R]

我正在與我的函數返回類型的問題。幾乎每種方法都有類型參數[R >: T : ClassManifest, A <: R : ClassManifest],TBlockList的類型參數。有時這些方法只會返回其他方法,但在這些情況下,我從Eclipse中得到一個錯誤,說它正在尋找類型BlockList[R],但發現類型爲BlockList[Any]。不應該RTA的最低通用超級類型?在這種情況下,第二個方法調用也應該返回BlockList[R],對吧?我沒有得到什麼?我反映ClassManifest很多以克服類型擦除的問題,但我不知道它是否仍然是一個問題。

的錯誤是從|::|的定義。

import collection.immutable.List 
import reflect.ClassManifest 
import annotation.tailrec 

sealed abstract 
class BlockList [+T] extends Seq[T] with Product { 
... 
} 

object EmptyBlock extends BlockList[Nothing] { 
... 
} 

class Build [T: ClassManifest](
private val block: IndexedSeq[T], 
private val next: BlockList[T] = EmptyBlock, 
private val index: Int = 0 
) extends BlockList[T] { 
require(!block.isEmpty && index >= 0 && index < block.length) 

override def |: [R >: T : ClassManifest, A <: R] (x: A): BlockList[R] = 
    Array[R](x) |: this //Return type error here 

override def |: [R >: T : ClassManifest, A <: R : ClassManifest] 
(blk: IndexedSeq[A]): BlockList[R] = 
    if (blk isEmpty) this 
    else new Build[R](blk, this) 

override def :| [R >: T : ClassManifest, A <: R] (x: A): BlockList[R] = 
    this :| Array[R](x) //Return type error here 

override def :| [R >: T : ClassManifest, A <: R : ClassManifest] 
(blk: IndexedSeq[A]): BlockList[R] = 
    if (blk isEmpty) this 
    else new Build[R](block, next :| blk, index) //Type error here 

} 
+0

我建議簡化到產生錯誤的最小可能的例子。 – Brian

+0

謝謝Brian。我接受了你的建議。 – Eric

回答

3

應該不屬於R是最低的公用超類型T和A的?

不,因爲R是上界。 R可以任何超類的T,並滿足該界是Any唯一的類。

想象一下,例如,該RAnyRef - 那麼你可以調用如eq就可以了,如果Int才通過了將打破。

所以,雖然R可以東西比Any低(可能會大部分時間),在聲明它的時候不能假定它是任何超過Any低。

不過,我覺得上面並沒有任何關係,與你的問題。您報告的錯誤出現在這些行中,對嗎?

Array[R](x) |: this 
this :| Array[R](x) 

另一個也有:|在裏面。你不顯示任何隱式轉換從ArrayBuild,沒有的:|方法採取Array作爲參數(數組不是IndexedSeq)。

所以,當你寫

this :| Array[R](x) 

這就需要def |: [R1 >: T : ClassManifest, A <: R1] (x: A): BlockList[R1](我已經改變了RR1 n要與參數的R混淆),其中的A類型是Array[R],唯一超類型TArray[R]Any,所以R1必須是Any,但是Any不同於R

也許,如果你叫它this.:|[R, Array[R]](Array[R](x)), it would move things a little further. With the missing definitions that allow Array`要通過,我不能預測其他許多。

+0

我的印象是'Array'被自動包裝爲'WrappedArray',它本身就是'IndexedSeq'。構造函數在代碼中接受'Array'參數,所以在我看來它有時會被自動包裝。 (本來'block'是一個'Array [T]',但'Array'的不變性導致了太多問題。)我將這些'Array [R](x)'調用改爲'(Array [R](x) toIndexedSeq)',這似乎解決了這個問題。現在我很困惑,在什麼情況下'Array'被隱式轉換爲'WrappedArray's。 – Eric