我正在尝试在Scala中实现隐式Not[T]
,因此,当类型T
的范围中存在隐式val时,我想引发编译器错误。我想到了使用模棱两可的隐式方法进行此操作,因为Scaladoc展示了一种实现=!=
的方法。 (请参见下文)
但是,我不明白为什么需要两个newAmbig
,因为如果我删除一个=!=
似乎仍然有一个模棱两可的隐含意义,因为最初似乎有3个可行的隐含意义。 (见下文)
我找不到有关编译器标记不明确的隐式内容所需的任何文档。
Scaladoc显示的trait =!=[C, D]
implicit def neq[E, F] : E =!= F = null
@annotation.implicitAmbiguous("Could not prove ${J} =!= ${J}")
implicit def neqAmbig1[G, H, J] : J =!= J = null
implicit def neqAmbig2[I] : I =!= I = null
implicitly[Int =!= Int]
的实现:
=!=
trait =!=[C, D]
implicit def neq[E, F] : E =!= F = null
@annotation.implicitAmbiguous("Could not prove ${J} =!= ${J}")
implicit def neqAmbig1[G, H, J] : J =!= J = null
implicitly[Int =!= Int]
的实现似乎可行,但无效:
neqAmbig1
因为neq
和null
应该是同一类型,并且都应该找到。
但是,这不会引发编译器错误,并且在测试时仅返回myOtherStream.transform(() -> new MyTransformer<>(), MY_STORE)
.leftJoin(myOtherKTable, new MyOtherValueJoiner<>(), Joined.with(JoinedKey.serde(), JoinedValue.serde(), JoinedValueOutput.serde()));
。
答案 0 :(得分:2)
isAsSpecific似乎是编译器的相关部分,该代码整理了规范中的重载分辨率规则,因此请查看是否可以解密这些规则:
/** Is type `ftpe1` strictly more specific than type `ftpe2`
* when both are alternatives in an overloaded function?
* @see SLS (sec:overloading-resolution)
*/
def isAsSpecific(ftpe1: Type, ftpe2: Type): Boolean
要确认您的第一个实现正确无误,请考虑{shape所提供的Type inequality
// Type inequalities
trait =:!=[A, B] extends Serializable
implicit def neq[A, B] : A =:!= B = new =:!=[A, B] {}
implicit def neqAmbig1[A] : A =:!= A = unexpected
implicit def neqAmbig2[A] : A =:!= A = unexpected
例如,
import shapeless.{<:!<, =:!=}
def foo[A](a: A)(implicit ev: A =:!= String): A = a
foo(3) // ok
foo("") // error: ambiguous implicit values
答案 1 :(得分:2)
让我们从简化和澄清情况开始。
这有效。隐式已按预期解决。
trait =!=[C, D]
implicit def neq[E, F] : E =!= F =
new =!=[E,F]{override def toString="NEQ"}
implicitly[Int =!= Int] //res0: Int =!= Int = NEQ
现在让我们添加应该是一个模糊的隐式。
trait =!=[C, D]
implicit def neq[E, F] : E =!= F =
new =!=[E,F]{override def toString="NEQ"}
implicit def neqAmbig1[E, F] : E =!= E =
new =!=[E,E]{override def toString="NeqAm1"}
implicitly[Int =!= Int] //res0: Int =!= Int = NeqAm1
嗯。对于Int =!= Int
,我们将E
设为Int
,将F
设为Int
,因此类型E =!= F
应该与{{ 1}},但是编译器并不认为它们是等效的,而是选择E =!= E
版本(无论隐式代码中定义的顺序如何)。
我相信language spec中描述了这里发生的事情:
如果有多个与隐式参数类型匹配的合格参数,则将使用静态重载解析规则选择一个最具体的参数。
这来自“隐式参数”部分,但我认为它仍然适用:类型E =!= E
比类型E =!= E
更特定于Int =!= Int
。