代码之家  ›  专栏  ›  技术社区  ›  e2rabi

在本例中对Scala泛型语法感到困惑

  •  0
  • e2rabi  · 技术社区  · 7 年前

    一些简单易懂的例子也很棒!

    0 回复  |  直到 13 年前
        1
  •  493
  •   Julian A.    6 年前

    我以为这已经被问到了,但是,如果是这样的话,这个问题在“相关”栏中并不明显。这就是:

    什么是视图边界?

    A. Scala中引入了一种机制来支持某种类型的 A 犹如 那是某种类型的 B 。典型的语法如下:

    def f[A <% B](a: A) = a.bMethod
    

    换句话说,, A. B 可供选择,以便拨打电话 。在标准库中(无论如何,在Scala 2.8.0之前),视图边界最常见的用法是 Ordered ,例如:

    def f[A <% Ordered[A]](a: A, b: A) = if (a < b) a else b
    

    因为一个人可以转化 Ordered[A] ,因为 命令的[A] <(other: A): Boolean a < b

    view bounds are deprecated ,你应该避开它们。

    什么是上下文约束?

    上下文边界是在Scala2.8.0中引入的,通常用于所谓的 ,这是一种代码模式,它模拟Haskell类型类提供的功能,但方式更为详细。

    A <% String 在上面,但不同于 String .

    上下文绑定描述隐式 价值 转变 。它用于声明某些类型的 ,存在类型为的隐式值 B[A] 可获得的语法如下所示:

    def f[A : B](a: A) = g(a) // where g requires an implicit value of type B[A]
    

    def f[A : ClassManifest](n: Int) = new Array[A](n)
    

    Array 参数化类型上的初始化需要 ClassManifest 由于与类型擦除和数组的非擦除性质相关的神秘原因,该文件将可用。

    库中另一个非常常见的示例稍微复杂一些:

    def f[A : Ordering](a: A, b: A) = implicitly[Ordering[A]].compare(a, b)
    

    在这里 implicitly 用于检索所需的隐式值,类型为 Ordering[A] ,哪个类定义了该方法 compare(a: A, b: A): Int

    我们将在下面看到另一种方法。

    def f[A <% B](a: A) = a.bMethod
    def f[A](a: A)(implicit ev: A => B) = a.bMethod
    
    def g[A : B](a: A) = h(a)
    def g[A](a: A)(implicit ev: B[A]) = h(a)
    

    因此,很自然,我们可以用完整的语法编写它们,这对于上下文边界特别有用:

    def f[A](a: A, b: A)(implicit ord: Ordering[A]) = ord.compare(a, b)
    

    视图边界主要用于利用 皮条客我的图书馆 模式,在希望以某种方式返回原始类型的情况下,通过该模式向现有类“添加”方法。如果不需要以任何方式返回该类型,则不需要视图绑定。

    .注意 Int 不是 命令 ,例如,尽管存在隐式转换。前面给出的示例需要视图绑定,因为它返回未转换的类型:

    def f[A <% Ordered[A]](a: A, b: A): A = if (a < b) a else b
    

    如果没有视图边界,此示例将无法工作。但是,如果要返回另一个类型,则不再需要视图绑定:

    def f[A](a: Ordered[A], b: A): Boolean = a < b
    

    这里的转换(如果需要)发生在我将参数传递给 f 所以 F

    此外 命令 一串 ,它们是Java类,就像Scala集合一样。例如:

    def f[CC <% Traversable[_]](a: CC, b: CC): CC = if (a.size < b.size) a else b
    

    一串 将是一个 WrappedString 大堆 .

    即使该类型仅用作返回类型的类型参数,也会发生同样的情况:

    def f[A <% Ordered[A]](xs: A*): Seq[A] = xs.toSeq.sorted
    

    上下文边界用于什么?

    类型类模式 ,作为对Haskell类型类的引用。基本上,此模式通过一种隐式适配器模式使功能可用,从而实现继承的替代方案。

    典型的例子是Scala 2.8 Ordering 整个Scala的图书馆。用法是:

    def f[A : Ordering](a: A, b: A) = if (implicitly[Ordering[A]].lt(a, b)) a else b
    

    def f[A](a: A, b: A)(implicit ord: Ordering[A]) = {
        import ord.mkOrderingOps
        if (a < b) a else b
    }
    

    它利用了内部的一些隐式转换 这将启用传统的运算符样式。Scala 2.8中的另一个示例是 Numeric

    def f[A : Numeric](a: A, b: A) = implicitly[Numeric[A]].plus(a, b)
    

    一个更复杂的例子是新的集合用法 CanBuildFrom ,但是已经有一个很长的答案,所以我在这里避免。如前所述,还有 类清单

    与typeclass模式绑定的上下文更有可能被您自己的类使用,因为它们支持关注点的分离,而视图边界可以通过良好的设计在您自己的代码中避免(它主要用于绕过其他人的设计)。

    虽然上下文边界的使用已经有很长一段时间了,但它在2010年已经真正开始使用,并且在某种程度上在大多数Scala最重要的库和框架中都可以找到。不过,它使用的最极端的例子是Scalaz库,它为Scala带来了Haskell的强大功能。我建议阅读typeclass模式,以便更好地了解它的所有使用方法。

    编辑

    推荐文章