trait Foo
trait Bar extends Foo
def doStuff[T <: Foo](x: T)(implicit ev: T =!:= Foo) = x
doStuff(new Foo{}) //ambiguous implicit value
doStuff(new Bar)// successful
隐式解析是在编译时发生的,所以在这里我认为可能有两个具有完全相同类型的隐式值要触发模糊的 stuff.
现在我准备把shapeless引入团队,我的同事们认为这种暧昧的隐含不太理想,对此我也没有什么强有力的论据。为了使 scala 中的类型安全,这是唯一的方法吗?如果是,我可以做什么来自定义错误消息?
Edit:
在无形中,我想让2个NAT之和不等于7,我可以这样编码,使编译失败。
def typeSafeSum[T <: Nat, W <: Nat, R <: Nat](x: T, y: W)
(implicit sum: Sum.Aux[T, W, R], error: R =:!= _7) = x
typeSafeSum(_3, _4)
但错误消息是不明确的隐式值,如何自定义错误消息?
在这个(和大多数其他)实例中,简单的类型类会比类型不等式测试更好。
大概是想要排除的原因Foo
就是它Bar
(及其兄弟姐妹)有一些属性Foo
缺乏。如果是这种情况,那么您应该创建一个类型类来捕获这些属性,并使其成为对类型参数的要求doStuff
。你可以使用Scala的@implicitNotFound
注释以使编译器错误消息在不满足该要求时更容易理解。
@annotation.implicitNotFound(msg = "No Props instance for ${T}")
trait Props[T] {
def wibble(t: T): Double
}
trait Foo
// Note no Props instance for Foo ...
trait Bar extends Foo
object Bar {
// Props instance for Bar
implicit def barProps: Props[Bar] = new Props[Bar] {
def wibble(t: Bar): Double = 23.0
}
}
def doStuff[T <: Foo](t: T)(implicit props: Props[T]) = props.wibble(t)
scala> doStuff(new Foo {})
<console>:11: error: No Props instance for Foo
doStuff(new Foo {})
^
scala> doStuff(new Bar {})
res1: Double = 23.0
如果没有任何这样的属性来区分Foo
from Bar
那么你应该质疑你需要排除的假设Foo
from doStuff
首先。
如果您在项目中使用 Shapeless,我会很高兴,但您应该使用=!:=
(以及 Scala 自己的=:=
)仅作为最后的手段(如果有的话)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)