2010-04-08 50 views
35

任何人都可以在斯卡拉提供<:<运算符的一些细节。 我认为:<:<斯卡拉运算符

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

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

+1

您是指'Manifest'上的方法还是'Predef'中定义的类? – 2010-04-08 21:49:16

+62

这就是所谓的“麦当娜穿着纽扣衬衫”的经营者。 – Syntactic 2010-05-07 14:34:57

+3

哈,我叫它“愤怒的驴子”运营商 – 2010-05-07 14:36:43

回答

23

<:<不是一个操作符 - 它是一个标识符,因此是以下之一:

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

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

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

对于Predef中的这种类型,这是相对较新的,我也对此略有困惑,因为它似乎是同样声明三重奏的一部分!

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

'Predef'中的那些是广义类型约束。这个邮件列表的主题覆盖了一些:http://old.nabble.com/-scala--Using-generalised-type-constraints-in-2.8-collections-td26249516.html – 2010-04-09 11:08:48

+1

但是从声明他们都看起来相同,那么他们怎么能意味着不同的事情呢? – 2010-04-09 11:12:05

+0

感谢您的链接:不幸的是,我仍然在努力去理解如何用隐含的ev:A <: B',其中'<:<[A,B] extends A => B'实际上*做任何事情 – 2010-04-09 11:39:50

7

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

例如:

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

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

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

3

从scala.Predef复制。阶:

// 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} 
30

<:<类型在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所述,可以使用此方法为仅适用于某些泛型类型实例的方法提供证据参数(给出的示例为仅可用于Tuple2TraversabletoMap方法)。正如在注释中指出的那样,这将一般的泛型类型约束泛化,以允许它引用任何范围内的抽象类型/类型参数。使用这种方法(implicit ev : T1 <:< T2)比单纯使用证据参数(如implicit ev: T1 => T2)的优势在于后者可能会导致意外的范围内隐式值用于转换。

我确定我在Scala的邮件列表上看到过这方面的一些讨论,但目前找不到它。

+0

<: Eastsun 2010-05-07 15:25:25

+2

@ Eastsun'<:<'承认子类,而'=:='不。 – 2010-05-07 15:29:17

+3

隐式参数'ev:T1 <: 2010-05-07 15:30:00

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 
            ^