<:其中scala中的运算符

时间:2010-04-08 19:56:37

标签: scala

任何人都可以在scala中提供<:<运算符的一些详细信息。 我想:

if(apple <:< fruit)  //checks if apple is a subclass of fruit.

还有其他解释吗?我在scala源文件中看到了很多定义。

8 个答案:

答案 0 :(得分:31)

<:<类型定义在Predef.scala以及相关类型=:=<%<中,如下所示:

// used, for example, in the encoding of generalized constraints
// we need a new type constructor `<:<` and evidence `conforms`, as 
// reusing `Function2` and `identity` leads to ambiguities (any2stringadd is inferred)
// to constrain any abstract type T that's in scope in a method's argument list (not just the method's own type parameters)
// simply add an implicit argument of type `T <:< U`, where U is the required upper bound (for lower-bounds, use: `U <: T`)
// in part contributed by Jason Zaugg
sealed abstract class <:<[-From, +To] extends (From => To)
implicit def conforms[A]: A <:< A = new (A <:< A) {def apply(x: A) = x} // not in the <:< companion object because it is also intended to subsume identity (which is no longer implicit)

这使用Scala功能,可以编写通用类型op[T1, T2] T1 op T2。如aioobe所述,这可用于为仅适用于泛型类型的某些实例的方法提供证据参数(给出的示例是toMap方法,只能在{{1}上使用} Traversable)。如注释中所述,这概括了一个普通的泛型类型约束,以允许它引用任何范围内的抽象类型/类型参数。使用此(Tuple2)优于简单地使用像(implicit ev : T1 <:< T2)这样的证据参数,因为后者可能会导致意外的范围内隐含值用于转换。

我确定我在其中一个Scala邮件列表上看到了一些关于此的讨论,但目前无法找到它。

答案 1 :(得分:26)

<:< 不是运营商 - 它是标识符,因此是以下之一:

  • 类型的名称(类,特征,类型别名等)
  • 方法/ val或var
  • 的名称

在这种情况下,<:<在库中出现两次,一次出现在Predef作为一个类,一次出现在Manifest上。

对于Manifest上的方法,它会检查清单所代表的类型是否是清单参数所代表的类型。

对于Predef中的类型,这是相对较新的,我也对它有点困惑,因为它似乎是三个相同声明的一部分!

class <%<[-From, +To] extends (From) ⇒ To
class <:<[-From, +To] extends (From) ⇒ To
class =:=[From, To] extends (From) ⇒ To

答案 2 :(得分:14)

我问了一下,这就是我得到的解释:

<:<通常用作证据参数。例如,在TraversableOnce中,toMap被声明为def toMap[T, U](implicit ev: A <:< (T, U)): immutable.Map[T, U]。这表示约束条件toMap方法仅在遍历包含2元组时才有效。 flatten是另一个例子。 <:<用于表示您只能展平可遍历的遍历的约束。

答案 3 :(得分:7)

实际上,它检查Manifest苹果所代表的是否是清单水果所代表的类的子类。

例如:

manifest[java.util.List[String]] <:< manifest[java.util.ArrayList[String]] == false
manifest[java.util.ArrayList[String]] <:< manifest[java.util.List[String]] == true

答案 4 :(得分:3)

从scala.Predef.scala复制:

// Type Constraints --------------------------------------------------------------

  // used, for example, in the encoding of generalized constraints
  // we need a new type constructor `<:<` and evidence `conforms`, as 
  // reusing `Function2` and `identity` leads to ambiguities (any2stringadd is inferred)
  // to constrain any abstract type T that's in scope in a method's argument list (not just the method's own type parameters)
  // simply add an implicit argument of type `T <:< U`, where U is the required upper bound (for lower-bounds, use: `U <: T`)
  // in part contributed by Jason Zaugg
  sealed abstract class <:<[-From, +To] extends (From => To)
  implicit def conforms[A]: A <:< A = new (A <:< A) {def apply(x: A) = x}

答案 5 :(得分:2)

更好地了解implementation

sealed abstract class <:<[-From, +To] extends (From => To)
implicit def conforms[A]: A <:< A = new (A <:< A) {def apply(x: A) = x}

我试图设计一个更简单的实现。以下不起作用。

sealed class <:<[-From <: To, +To]
implicit def conforms[A <: B, B]: A <:< B = new (A <:< B)

至少因为它不会在所有valid use个案例中键入签名。

case class L[+A]( elem: A )
{
   def contains[B](x: B)(implicit ev: A <:< B) = elem == x
}

error: type arguments [A,B] do not conform to class <:<'s
       type parameter bounds [-From <: To,+To]
def contains[B](x: B)(implicit ev: A <:< B) = elem == x
                                     ^

答案 6 :(得分:1)

嗯......我似乎无法找到“&lt;:&lt;”在任何地方,但“&lt ;:”表示子类型。 来自http://jim-mcbeath.blogspot.com/2008/09/scala-syntax-primer.html#types

List[T] forSome { type T <: Component }
  

在上面的例子中,我们说T是某种类型,它是Component的子类型。

答案 7 :(得分:0)

从消息来源我们有以下解释:

  /**
   * An instance of `A <:< B` witnesses that `A` is a subtype of `B`.
   * Requiring an implicit argument of the type `A <:< B` encodes
   * the generalized constraint `A <: B`.
   *
   * @note we need a new type constructor `<:<` and evidence `conforms`,
   * as reusing `Function1` and `identity` leads to ambiguities in
   * case of type errors (`any2stringadd` is inferred)
   *
   * To constrain any abstract type T that's in scope in a method's
   * argument list (not just the method's own type parameters) simply
   * add an implicit argument of type `T <:< U`, where `U` is the required
   * upper bound; or for lower-bounds, use: `L <:< T`, where `L` is the
   * required lower bound.
   *
   * In part contributed by Jason Zaugg.
   */
  @implicitNotFound(msg = "Cannot prove that ${From} <:< ${To}.")
  sealed abstract class <:<[-From, +To] extends (From => To) with Serializable
  private[this] final val singleton_<:< = new <:<[Any,Any] { def apply(x: Any): Any = x }
  // The dollar prefix is to dodge accidental shadowing of this method
  // by a user-defined method of the same name (SI-7788).
  // The collections rely on this method.
  implicit def $conforms[A]: A <:< A = singleton_<:<.asInstanceOf[A <:< A]

  @deprecated("Use `implicitly[T <:< U]` or `identity` instead.", "2.11.0")
  def conforms[A]: A <:< A = $conforms[A]

  /** An instance of `A =:= B` witnesses that the types `A` and `B` are equal.
   *
   * @see `<:<` for expressing subtyping constraints
   */
  @implicitNotFound(msg = "Cannot prove that ${From} =:= ${To}.")
  sealed abstract class =:=[From, To] extends (From => To) with Serializable
  private[this] final val singleton_=:= = new =:=[Any,Any] { def apply(x: Any): Any = x }
  object =:= {
     implicit def tpEquals[A]: A =:= A = singleton_=:=.asInstanceOf[A =:= A]
  }