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

在Scala 2.8中,<:<、<%<和=:=是什么意思?它们在哪里被记录?

  •  188
  • Jeff  · 技术社区  · 16 年前

    Predef 它们是泛型函数类型的子类(From)=>是的,但仅此而已。嗯,什么?也许有些文档,但搜索引擎不会处理像“<”这样的“名字”:&中尉很好,所以我还没找到。

    4 回复  |  直到 7 年前
        1
  •  222
  •   Tom Crockett    16 年前

    这些被称为 广义类型约束 . 它们允许您从类型参数化类或trait中 进一步约束

    case class Foo[A](a:A) { // 'A' can be substituted with any type
        // getStringLength can only be used if this is a Foo[String]
        def getStringLength(implicit evidence: A =:= String) = a.length
    }
    

    隐含论点 evidence 由编译器iff提供 A String 那个 字符串 [编辑:从技术上讲,它实际上很重要,因为它代表了从 A 字符串 ,这是允许您调用 a.length 别让编译器对你大喊大叫]

    scala> Foo("blah").getStringLength
    res6: Int = 4
    

    Foo 包含一个 :

    scala> Foo(123).getStringLength
    <console>:9: error: could not find implicit value for parameter evidence: =:=[Int,String]
    

    您可以将该错误理解为“找不到Int==String的证据”。。。这是应该的! getStringLength 论教育的类型 A 一般要求;也就是说,你只能调用 Foo[String] . 这个约束是在编译时强制执行的,这很酷!

    <:< <%< 工作方式类似,但略有不同:

    • A =:= B 意思是A必须正好是B
    • A <:< B 类型约束 <: )
    • A <%< B 可视的 作为B,可能通过隐式转换(类似于简单类型约束) <%

    This snippet @retronym很好地解释了这类事情过去是如何完成的,以及泛化类型约束现在是如何使它变得更容易。

    附录

    为了回答你接下来的问题,我举的例子是非常做作的,而且没有明显的用处。但是想象一下用它来定义 List.sumInts List ,只是一个 List[Int] 列表 类型构造函数不能这样约束;您仍然希望能够拥有字符串、foos、bar等等的列表。所以通过在 sumInts ,您可以确保 就是那个方法 列表

        2
  •  55
  •   Jesper    16 年前

    不是一个完整的答案(其他人已经回答了这个问题),我只想注意以下几点,这可能有助于更好地理解语法:您通常使用这些“运算符”的方式,例如pelotom的示例:

    def getStringLength(implicit evidence: A =:= String)
    

    利用Scala的替代方案 infix syntax for type operators .

    A =:= String 与相同 =:=[A, String] (和 =:=

    val a: Tuple2[Int, String] = (1, "one")
    

    这样地:

    val a: Int Tuple2 String = (1, "one")
    

    它类似于方法调用的两个语法,“normal”和 . () 以及运算符语法。

        3
  •  40
  •   Tom Crockett    14 年前

    阅读其他答案,了解这些结构是什么。这里是 你应该使用它们。当需要仅为特定类型约束方法时,可以使用它们。

    下面是一个例子。假设要定义一个齐次对,如下所示:

    class Pair[T](val first: T, val second: T)
    

    smaller ,如下所示:

    def smaller = if (first < second) first else second
    

    T 已订购。您可以限制整个类:

    class Pair[T <: Ordered[T]](val first: T, val second: T)
    

    T型 方法:

    def smaller(implicit ev: T <:< Ordered[T]) = if (first < second) first else second
    

    可以实例化,比如说,一个 Pair[File] , 较小 在上面。

    如果是 Option orNull 方法,即使它对 Option[Int] 奥努尔 Option[String] 并且使用它,只要你不打电话 奥努尔 在上面。如果你尝试 Some(42).orNull

     error: Cannot prove that Null <:< Int
    
        4
  •  17
  •   Daniel C. Sobral    16 年前

    Manifest 物体。它们在内部定义 scala.Predef 在前两个案例中,虽然没有很好的记录。

    <: <% 在后者不能使用的情况下。

    至于“我应该什么时候使用它们”这个问题,答案是你不应该,除非你知道你应该这样做 :好的,好的,这里有一些来自图书馆的例子。在 Either ,您有:

    /**
      * Joins an <code>Either</code> through <code>Right</code>.
      */
     def joinRight[A1 >: A, B1 >: B, C](implicit ev: B1 <:< Either[A1, C]): Either[A1, C] = this match {
       case Left(a)  => Left(a)
       case Right(b) => b
     }
    
     /**
      * Joins an <code>Either</code> through <code>Left</code>.
      */
     def joinLeft[A1 >: A, B1 >: B, C](implicit ev: A1 <:< Either[C, B1]): Either[C, B1] = this match {
       case Left(a)  => a
       case Right(b) => Right(b)
     }
    

    Option

    def orNull[A1 >: A](implicit ev: Null <:< A1): A1 = this getOrElse null
    

    你会发现一些其他的例子。

    推荐文章