在定义函数时,我可以创建一个隐式参数列表,该列表引用前面显式参数列表中的变量,但在定义类时则不行。我做错了吗?
为了说明,让我们制作一些对象。这里的目的是创建一个幻像类型的层次结构来“标记”对象的层次结构。我希望隐式ev
保证对象来自正确的层次结构。
trait Token {
type Phantom
}
object TopToken extends Token {
trait Phantom
}
object SubToken extends Token {
trait Phantom <: TopToken.Phantom
}
object ForeignToken extends Token {
trait Phantom // doesn't extend TopToken.Phantom
}
def f(t: Token)(implicit ev: t.Phantom <:< TopToken.Phantom) { println(t) }
函数f
正常工作:
scala> f(SubToken)
$line5.$read$$iw$$iw$SubToken$@76c2539f
scala> f(ForeignToken) // This should fail.
<console>:12: error: Cannot prove that ForeignToken.Phantom <:< TopToken.Phantom.
f(ForeignToken)
^
但请注意当我使用相同的参数列表来定义类时会发生什么:
scala> class F(t: Token)(implicit ev: t.Phantom <:< TopToken.Phantom)
<console>:9: error: not found: value t
class F(t: Token)(implicit ev: t.Phantom <:< TopToken.Phantom)
^
我正在运行Scala 2.11.2。
更新进一步的实验表明,implicit
没有任何区别。
答案 0 :(得分:1)
如果您参数化F
类,则可以使用以下语法实现此目的。
class F[T <: Token](t: T)(implicit ev: T#Phantom <:< TopToken.Phantom) { }
该类现在采用一个类型参数,该参数必须是Token
的子类型。然后,在限制允许的Phantom
类型时,隐式证据可以通过类型参数引用具体Token
中的Token
类型。
scala> class F[T <: Token](t: T)(implicit ev: T#Phantom <:< TopToken.Phantom) { }
defined class F
scala> new F(SubToken)
res1: F[SubToken.type] = F@6d26561b
scala> new F(ForeignToken)
<console>:15: error: Cannot prove that ForeignToken.Phantom <:< TopToken.Phantom.
new F(ForeignToken)
^