构造函数无法实例化为期望的类型

时间:2017-04-19 19:32:56

标签: scala

我正在使用Scala 2.11.8

我有这段代码

run

IDE(IntelliJ 2017.1)未显示任何错误。但是当我从SBT编译时。它说

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 {...}

这让我疯了,因为在REPL。我可以轻松编写此代码。

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

1 个答案:

答案 0 :(得分:3)

简短的回答是Either并不适合理解(至少在scala&lt; 2.11中)。

所以你首先要记住,因为理解是monadic操作mapflatMapwithFilter的语法糖。

特别是,在对提取的值(例如代码中的(c, d) <- i2.right)进行模式匹配时,会将其替换为(相当于某些内容)

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

现在您可以更清楚地看到问题所在:首先,withFilter上没有RightProjection方法,因此它使用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是如何去掉的话,会给你一些令人困惑的错误信息。)< / p>

一般情况下,如果要进行某些过滤(包括模式匹配)或分配,则应避免使用Either进行理解。您可能希望在某些库中考虑一些等效的monad,例如catz或scalaz中的Validation\/

NB 我说了scala 2.11,因为在scala 2.12中,Either变得正确偏见,所以上面提到的一些问题消失了,但我还没有我已经尝试过了。