Scala:使用参数化函数类型

时间:2014-12-03 00:53:31

标签: scala either

Either应该使用参数化函数吗?

case class FunOrSeq[T1, T2](e: Either[Function1[T1, T2], Iterable[T1]])

def f: Int => Int = x => x

scala> FunOrSeq(Left(f))
<console>:11: error: type mismatch;
 found   : scala.util.Left[Int => Int,Nothing]
 required: Either[T1 => Int,Iterable[T1]]
          FunOrSeq(Left(f))

这让我感到惊讶 - 它适用于显式类型:

scala> case class FunOrSeq[T1, T2](e: Either[(Int => Int), Iterable[T1]])
defined class FunOrSeq

scala> FunOrSeq(Left(f))
res6: FunOrSeq[Nothing,Nothing] = FunOrSeq(Left(<function1>))

2 个答案:

答案 0 :(得分:3)

问题在于,因为Iterable分支也获得了T1,所以Function1分支不允许将其修改为Int(它不仅仅是{{}} 1}};具有用于协变和逆变类型参数的相同类型参数往往在类型推理引擎上很难)。您可以通过添加更多类型参数并让Function1Iterable更窄来坚持编译器允许这样做:

Function1

如果你想要它们真的相同,你可以添加一个隐含的强制它们是相同的:

case class FunOrSeq[A, B, AA <: A](e: Either[A => B, Iterable[AA]])

scala> FunOrSeq(Left(f))
res0: FunOrSeq[Int,Int,Nothing] = FunOrSeq(Left(<function1>))

答案 1 :(得分:1)

我不确定编译器决策背后的原因是什么,但是在两者中都有T1的事实会使类型系统混乱。如果添加一个参数使Iterable [T3]与T1不同,它似乎可以工作。

scala> case class FunOrSeq2[T1, T2, T3](e: Either[Function1[T1, T2], Iterable[T3]])
defined class FunOrSeq2

scala> FunOrSeq2(Left(f2))
res12: FunOrSeq2[Int,String,Nothing] = FunOrSeq2(Left(<function1>))