2016-03-15 34 views
2

斯卡拉11.2是給我這個錯誤:神祕的GADT skolem:什麼類型試圖逃避其範圍?

error: type mismatch; 
found : Seq[Some[V]] 
required: Seq[Option[?V8]] where type ?V8 <: V (this is a GADT skolem) 
      val output = f(ivs.map(iv => Some(iv.get._1))) 
           ^

首先,這似乎是一個奇怪的錯誤信息:不序列[某些[V]符合序列[選項[V]?

這裏是周圍的代碼,似乎相關的部分:

def evalDependencyTree[V] 
    (linkRelevance: LinkInfo => Option[LinkStrength]) 
    (dtree: DependencyTree[V, LinkInfo], strengthSoFar: LinkStrength = 1.0) 
    : Option[(V, LinkStrength)] = dtree match { 
    . . . 
    case DFunction(f, inputs) => { 
     val ivs = inputs.map { input => 
     evalDependencyTree(linkRelevance)(input, strengthSoFar) // <-- Recursive call 
     } 
     val output = f(ivs.map(iv => Some(iv.get._1))) // <-- The line with the error 
     . . . 
    } 
    } 

    trait DependencyTree[+V, +L] 

    case class DFunction[V, L](
    f: Seq[Option[V]] => Option[V], inputs: Seq[DependencyTree[V, L]]) 
    extends DependencyTree[V, L] 

我GADT skolems的(非常有限)的理解是,他們是類型推斷期間由編譯器定義的類型,複製現有的類型參數,以防止該類型「轉義」其作用域,例如在遞歸調用中 - 也就是說,爲了防止它從無法訪問類型的更大範圍引用。

我不明白V在這裏可以引用不同範圍的不同類型。對evalDependencyTree的遞歸調用具有與evalDependencyTree的當前調用相同的類型參數V。我試着爲遞歸調用明確地編寫evalDependencyTree[V],但編譯器返回了相同的錯誤消息。當evalDependencyTree沒有類型參數時,此代碼確實有效;在該版本中,dtree被硬編碼爲DependencyTree[Int, LinkInfo]

什麼類型試圖逃脫?或者說,我做錯了什麼?

回答

1

我找到了一個解決方法自己:明確地拼寫出完整的類型的f的模式匹配,就像這樣:

case DFunction(f: Seq[Option[V]] => Option[V], inputs) => . . . 

這工作,但我不接受它,因爲我不回答沒有解釋爲什麼這是必要的。我仍然不知道什麼時候會出現這種錯誤或導致錯誤的原因。如果你知道,請發表一個答案!

此外,我會認爲明確提供的f類型的大多數類型已被類型刪除丟失。所以,我無法解釋這個解決方法有兩件重要的事情。

+0

發現你的問題在[這個問題]的上下文中(https://stackoverflow.com/questions/41183928/scala-properly-defining-a-empty-value-for-a-abstract-data-type)和我認爲你可以很容易地在[我的答案](http://stackoverflow.com/a/41184478/614394)中構建類似的classCastException事件, –