scala - 高阶函数将类型T更改为Nothing
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了scala - 高阶函数将类型T更改为Nothing相关的知识,希望对你有一定的参考价值。
故障排除环境: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.Nothing是其他类型的子类型,所以我想也许它正在丢失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)_
如果我一次性应用它(在顶部使用第一个'func'),它可以正常工作......
val g1 = func(true)(10.0, 1)
// g1: Double = 10.0
但在我的真实(非玩具)代码中,这不是一个选择。
这里发生了什么,如何在部分应用时使func
工作?
编辑[@Alexey的解决方案]
我不能得到首选的'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)
当我尝试部分应用
isValid
时,我希望结果是(T, Int) => Double
类型
值不能是通用的。因此,对于某些特定的T
,它可以具有此类型,但是您没有提供允许推断它的确切参数。你可以指定例如
val f1 = func[TheTypeYouWant](true) _
要么
val f1: (TheTypeYouWant, Int) => Double = func(true) _
如果你想要它是通用的,它必须再次是def
:
def f1[T <% Double] = func[T](true) _
以上是关于scala - 高阶函数将类型T更改为Nothing的主要内容,如果未能解决你的问题,请参考以下文章
2021年大数据常用语言Scala(三十七):scala高级用法 高阶函数用法