Устранение неполадок env: консоль sbt (Scala 2.11.8) и spark-shell (Spark 2.3, Scala 2.11)
У меня есть функция высшего порядка с типом привязки вида T ... ноэта сигнатура типа arg t: T
меняется с T <% Double
на Nothing
, когда функция применяется частично.
Пример игрушки для демонстрации:
// tot: T needs to work on (at least) Int, Long, Double, Float
// no common supertype -> some kind of context bound
def func[T <% Double](isValid: Boolean)(tot: T, cnt: Int): Double =
if (isValid) tot.toDouble / cnt else Double.NaN
Когда я пытаюсь частично применить isValid, Я ожидаю, что результатом будет тип (T, Int) => Double
, но вместо этого тип заканчивается (Nothing, Int) => Double
, и я не могу передать arg tot
.
val f1 = func(true)_ // f1: (Nothing, Int) => Double = <function2>
val f2 = func(false)_ // f2: (Nothing, Int) => Double = <function2>
val g1 = f1(10.0, 1)
// <console>:40: error: type mismatch;
// found : Double(10.0)
// required: Nothing
// val g1 = f1(10.0, 1)
Я не получаю никаких сообщений об ошибкахпри определении f1 или f2 ... так что трудно интерпретировать.Он просто конвертирует arg tot: T
в тип Nothing
.
Проверка scala doc ... Я вижу scala. Ничто не является подтипом КАЖДОГО другого типа, поэтому я подумал, что, возможно, он теряет вид, связанный с T... что, возможно, было связано с стиранием типов ... поэтому я попытался использовать ClassTag ...
import scala.reflect.ClassTag
def func[T <% Double](isValid: Boolean)(tot: T, cnt: Int)(implicit tag: ClassTag[T]): Double =
if (isValid) tot.toDouble / cnt else Double.NaN
Это не помогает.Та же проблема.
, если я попытаюсь использовать implicit num: Numeric[T]
, он задушит тип Nothing
по-новому ...
def func[T](isValid: Boolean)(tot: T, cnt: Int)( implicit num: Numeric[T] ): Double =
if (isValid) num.toDouble(tot) / cnt else Double.NaN
val f1 = func(true)_
// <console>:40: error: could not find implicit value for parameter num: Numeric[Nothing]
// val f1 = func(true)_
Если применить все сразу (используя first 'func 'наверху), он отлично работает ...
val g1 = func(true)(10.0, 1)
// g1: Double = 10.0
Но в моем реальном (не игрушечном) коде это не вариант.
Что здесь происходит и какможно ли заставить func
работать при частичном применении?
РЕДАКТИРОВАТЬ [@ решение Алексея]
Я не могу получить предпочтительный подход 'def' к работе.
def func[T <% Double](isValid: Boolean)(tot: T, cnt: Int): Double =
if (isValid) tot.toDouble / cnt else Double.NaN
// func: [T](isValid: Boolean)(tot: T, cnt: Int)(implicit evidence$1: T => Double)Double
def f1[T <% Double]: ((T, Int) => Double) = func[T](true)_
// f1: [T](implicit evidence$1: T => Double)(T, Int) => Double
f1[Double](10.0, 1)
<console>:41: error: too many arguments for method f1: (implicit evidence$1: Double => Double)(Double, Int) => Double
f1[Double](10.0, 1)