2017-04-19 78 views
1

我使用Scala的2.11.8構造函數不能被實例化預期型

我有這樣的代碼

val i1 = Either[ErrorCode, Person] = getMaybePerson().toRight(ErrorCode.NOTFOUND) 
val i2 = Either[ErrorCode, (Int, FiniteDuration)] = getMaybeConfig().toRight(ErrorCode.NOCONFIG) 
for { 
    a <- i1.right 
    (c, d) <- i2.right 
} yield {...} 

的IDE(的IntelliJ 2017.1)不顯示任何錯誤。但是當我從SBT編譯。它說

Warning:(163, 43) `withFilter' method does not yet exist on scala.util.Either.RightProjection[ErrorCode,(Int, scala.concurrent.duration.FiniteDuration)], using `filter' method instead 
    (maxReward, checkDuration) <- i2.right 
Error:(163, 10) constructor cannot be instantiated to expected type; 
found : (T1, T2) 
required: scala.util.Either[Nothing,(Int, scala.concurrent.duration.FiniteDuration)] 
     (maxReward, checkDuration) <- i2.right 

這使我瘋了,因爲在REPL。我可以很容易地編寫這段代碼。

Welcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_121). 
Type in expressions for evaluation. Or try :help. 

scala> case class Person(name: String, age: Int) 
defined class Person 

scala> val x = Some(Person("foo", 20)) 
x: Some[Person] = Some(Person(foo,20)) 

scala> val y = Some(("foo", 20)) 
y: Some[(String, Int)] = Some((foo,20)) 

scala> for { 
    | a <- x.toRight("wrong").right 
    | b <- y.toRight("wrong").right 
    | } yield (a.name, a.age, b._1, b._2) 
res0: scala.util.Either[String,(String, Int, String, Int)] = Right((foo,20,foo,20)) 

scala> 
+0

仔細檢查類路徑,確保沒有版本污染正在進行。 –

回答

3

簡短的回答是,Either沒有爲內涵坐好與(至少在斯卡拉< 2.11)。

所以,你首先必須記住的是,對於理解來說,一元操作是語法糖map,flatMapwithFilter

特別是,提取的價值做模式匹配時(如在代碼中(c, d) <- i2.right),這是由(東西相當於)

i2.right.withFilter(_.isInstanceOf[Tuple2[A, B]]).map{p => 
    val (c, d) = p.asInstanceOf[Tuple2[A, B]] 
    ... 
} 

現在你可以更清楚地看到問題更換是:首先,在RightProjection上沒有withFilter方法,所以它使用filter代替(如錯誤說明所述)。然後filter方法輸出一個Option[Either[ErrorCode, (Int, FiniteDuration)]],所以你不能模式匹配元組反對它。

如果能夠圍繞filter問題搞定了,你可能會來攻擊與map的問題(我知道我做了): 如果您嘗試使用在理解的分配:

for { 
    a <- Right("foo").right 
    b = a + "bar" 
} yield a + b 

此次榮獲」因爲它被map呼叫替換爲Either ...但由於Either不是右偏(或左),所以它沒有map方法,所以編譯器會丟失(並給你一些令人困惑的錯誤信息,如果你不考慮for是如何去除的)。

一般來說,如果您想要進行一些過濾(包括模式匹配)或分配,您應該避免使用Either來理解。您可能需要考慮一些庫中的一些等效monad,例如在catz或scalaz中的Validation\/

NB我說了一些關於斯卡拉2.11,因爲在斯卡拉2.12,Either成爲右偏,所以一些上述問題消失了,但我還沒有嘗試過我的手呢。

相關問題