<: <оператор в Scala - PullRequest
       24

<: <оператор в Scala

38 голосов
/ 08 апреля 2010

Может кто-нибудь предоставить некоторые подробности об операторе <:< в Scala. Я думаю:

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

Есть ли другие объяснения? Я вижу много определений в исходном файле scala.

Ответы [ 7 ]

31 голосов
/ 07 мая 2010

Тип <:< определен в 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, который можно использовать только для Traversable из Tuple2). Как отмечено в комментарии, это обобщает обычное ограничение универсального типа, чтобы позволить ему ссылаться на любой абстрактный тип / параметр типа в области видимости. Использование этого (implicit ev : T1 <:< T2) имеет преимущество перед простым использованием параметра подтверждения, такого как (implicit ev: T1 => T2), в том, что последний может привести к непреднамеренным неявным значениям в области действия, используемым для преобразования.

Я уверен, что видел какое-то обсуждение этого вопроса в одном из списков рассылки Scala, но пока не могу его найти.

26 голосов
/ 09 апреля 2010

<:< - это , а не оператор - это идентификатор и, следовательно, один из:

  • имя типа (класс, черта, псевдоним типа и т. Д.)
  • название метода / val или var

В этом случае <:< появляется дважды в библиотеке, один раз в Predef как класс и один раз как метод в Manifest.

Для метода на Manifest он проверяет, является ли тип, представленный , этим манифестом, является подтипом типа, представленного аргументом манифеста.

Для типа в Predef это относительно ново, и я также немного смущен этим, потому что он, кажется, является частью триумвирата идентичных объявлений!

class <%<[-From, +To] extends (From) ⇒ To
class <:<[-From, +To] extends (From) ⇒ To
class =:=[From, To] extends (From) ⇒ To
14 голосов
/ 07 мая 2010

Я спросил, и вот объяснение, которое я получил:

<:< обычно используется в качестве параметра доказательства. Например, в TraversableOnce, toMap объявлено как def toMap[T, U](implicit ev: A <:< (T, U)): immutable.Map[T, U]. Это выражает ограничение на то, что метод toMap работает, только если traversable содержит 2 кортежа flatten является еще одним примером. <:< используется для выражения ограничения, что вы можете сгладить только проходимый из проходимых.

7 голосов
/ 09 апреля 2010

На самом деле, он проверяет, является ли класс , представленный яблоком Manifest, подклассом класса, представленного проявленным фруктом.

Например:

manifest[java.util.List[String]] <:< manifest[java.util.ArrayList[String]] == false
manifest[java.util.ArrayList[String]] <:< manifest[java.util.List[String]] == true
3 голосов
/ 07 мая 2010

Копировать из 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}
2 голосов
/ 04 декабря 2011

Чтобы лучше понять реализацию .

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)

Хотя бы потому, что не будет проверять тип во всех допустимых случаях использования .

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
                                     ^
1 голос
/ 07 мая 2010

Хмм ... Кажется, я нигде не могу найти "<: <", но "<:" обозначает подтип. From <a href="http://jim-mcbeath.blogspot.com/2008/09/scala-syntax-primer.html#types" rel="nofollow noreferrer">http://jim -mcbeath.blogspot.com / 2008/09 / scala-syntax-primer.html # types :

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

В приведенном выше примере мы говорим, что T - это некоторый тип, который является подтипом Component.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...