简体   繁体   English

Scala:具有参数化函数类型

[英]Scala: Either with parameterized function type

Should Either work with parameterized functions? 是否应该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))

Which was surprising to me - it works with explicit types: 这让我感到惊讶-它适用于显式类型:

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>))

The problem is that because the Iterable branch also gets a T1 , the Function1 branch isn't allowed to fix it as Int (it's not just Function1 ; having the same type parameter used for both covariant and contravariant type arguments tends to be tough on the type inference engine). 问题在于,因为Iterable分支也获得了T1 ,所以不允许Function1分支将其修复为Int (这不仅是Function1 ;对于协变量和反变量类型参数使用相同的类型参数往往对T1很难。类型推断引擎)。 You can insist that the compiler allow this by adding more type parameters and letting the Iterable be narrower than the Function1 : 您可以通过添加更多的类型参数并使IterableFunction1窄来坚持要求编译器允许这样做:

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>))

And if you want them to really be the same, you can add an implicit to force them to be the same: 如果您希望它们确实相同,则可以添加一个隐式强制它们相同:

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

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

I'm not sure what the reason is here behind the compiler's decisions, but the fact that you have T1 on both sides of the either is confusing the type system. 我不确定编译器决定背后的原因是什么,但是任何一方的两侧都有T1的事实会混淆类型系统。 If you add a parameter to make Iterable[T3] different from T1, it seems to work. 如果添加参数以使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>))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM