В случае List(1,2,3).collect{case x => x.toString}
компилятор может определить тип ввода частичной функции на основе от того, как List
набралось.
final override def collect[B, That](pf: PartialFunction[A, B])(implicit bf: CanBuildFrom[List[A], B, That])
Основываясь на параметрах типа, компилятор может сделать вывод о том, что вы передаете правильно типизированную частичную функцию. Вот почему List(1,2,3).collect{case x:String => x.toString}
не компилируется, не делает List(1,2,3).collect{case x:Int => x.toString; case x: String => x.toString}
.
С List
является ковариантным, что компилятор способен заключить, что частичная функция {case x => x.toString}
является частичной функцией на Int
. Вы заметите, что List(1,2,3).collect{case x => x.length}
не компилируется, потому что компилятор выдает, что вы работаете либо с Int
, либо с подклассом Int
.
Также имейте в виду, что {case x => x.toString}
- это просто синтаксический сахар. Если мы делаем что-то вроде ниже, то ваш пример работает, как ожидалось
val f = new PartialFunction[Int, String](){
override def isDefinedAt(x: Int): Boolean = true
override def apply(v1: Int): String = v1.toString
}
val foo = PartialFunction[Int, String] { case 1 => "foo" }
val bar = foo orElse f //This compiles fine.
List(1,2,3).collect{f} // This works as well.
Таким образом, единственный логический ответ с моей точки зрения является то, что синтаксический сахар, который способен генерировать PartialFunction
экземпляр для {case x => x.toString}
не имеет достаточно информации по компиляции чтобы иметь возможность адекватно ввести его как PartialFunction[Int, String]
в вашем orElse
корпусе.
'collect' ожидает' [A частично определённой функции, B] 'а' orElse' ожидает '[A1 <: A, B1 >: B] частично определённая функция [A1, B1] ', так что в то время как компилятор может вывести первый, вам как-то нужно помогать со вторым. –
Спасибо, @PeterNeyens, что объясняет это для меня. Опубликуйте его как ответ, вы заботитесь о 25 пунктах. bump :) – Dima