2014-12-03 5 views
0

Должно ли Either работать с параметризованными функциями?Scala: Либо с параметризованным типом функции

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

Не ответ, но ваш первый пример работает, если вы явно передаете параметры типа в 'Left'. 'FunOrSeq (Left [(Int => Int), Iterable [Int]] (f))' Кажется, он не может не понять, что '[Int => Int, Nothing]' удовлетворяет '[T1 => Int, Iterable [T1]] ' – Falmarri

ответ

3

Проблема заключается в том, что, поскольку Iterable ветвь также получает T1, то Function1 ветвь не может исправить это как Int (это не только Function1, имеющие один и тот же параметр типа, используемый как для коварианта и контравариантного типа аргументы имеют тенденцию быть жесткими по отношению к механизму вывода типа). Вы можете настаивать на том, что компилятор позволяет это путем добавления дополнительных параметров типа и позволяя Iterable быть более узким, чем 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>)) 

И если вы хотите, чтобы они на самом деле то же самое, вы можете добавить неявное, чтобы заставить их то же самое:

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

 Смежные вопросы

  • Нет связанных вопросов^_^