【问题标题】:Understanding multiple parameter types in Scala Type Parameterization理解 Scala 类型参数化中的多种参数类型
【发布时间】:2017-02-07 05:24:37
【问题描述】:

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

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

但是,今天我发现了以下具有多种参数类型的类型参数化实现,并且由于我是 scala 的初学者,我完全无法理解它的实际作用。这是否意味着 T 必须是 Command、Foo 或 Bar 的子类型?

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

【问题讨论】:

    标签: scala


    【解决方案1】:

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

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

    真的是:def f[N](n: N)(implicit ev: Numeric[N]) = ...

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

    因此,在您的示例代码片段中:def getSomeValue[T &lt;: 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
    

    【讨论】:

    • 感谢您举例说明。
    【解决方案2】:

    这是否意味着 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 了解更多信息。

    【讨论】:

    • 我从来不知道上下文边界。谢谢你指出这一点。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-25
    • 1970-01-01
    • 2011-02-19
    • 2011-10-05
    • 2012-09-23
    • 2018-09-24
    • 1970-01-01
    相关资源
    最近更新 更多