了解Scala类型参数化中的多个参数类型

时间:2017-02-07 05:24:37

标签: scala

我理解以下是scala中上限类型参数化的示例,其中T必须是Command的子类型。

def getSomeValue[T <: Command] = ...

然而,今天我发现了以下带有多种参数类型的类型参数化实现,而且作为scala的初学者,我很难理解它实际上是做什么的。这是否意味着T必须是Command,Foo或Bar的子类型?

def getSomeValue[T <: Command : Foo : Bar] = ...

2 个答案:

答案 0 :(得分:3)

  

这是否意味着T必须是Command,Foo或Bar的子类型?

不,T仍需要上限。调用此方法时,您现在还必须在范围内具有Foo[T]Bar[T]隐式实例。这称为Context Bounds,它的语法糖为:

def getSomeValue[T <: Command](implicit f: Foo[T], b: Bar[T])

如果你不知道隐含的含义,refer to the documentation了解更多。

答案 1 :(得分:3)

在类型参数规范中,独立冒号实际上是一个较长(相当复杂)的参数调用的简写(语法糖)。

示例:def f[N: Numeric](n: N) = ...

确实是:def f[N](n: N)(implicit ev: Numeric[N]) = ...

意味着在调用f(x)时,必须有一个与Numeric[x.type]匹配的隐式范围。

因此,在您的示例代码片段中:def getSomeValue[T <: Command : Foo : Bar] = ...

编译器大致将其转换为以下内容:

def getSomeValue[T <: Command](implicit ev1: Foo[T], ev2: Bar[T]) = ...

我们可以通过提供足够的骨架代码来实现它的可编译性来证明这一点。

class Command {}
class Foo[F] {}
class Bar[B] {}
class Cmd extends Command

def getSomeValue[T <: Command : Foo : Bar](t: T) = t

getSomeValue(new Cmd)(new Foo[Cmd], new Bar[Cmd])
                  // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                  // implicit parameters supplied explicitly