Подтвердить что ты не робот

Оператор <: <в scala

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

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

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

4b9b3361

Ответ 1

<:< не оператор - он является идентификатором и поэтому является одним из:

  • имя типа (класс, признак, псевдоним типа и т.д.)
  • имя метода /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

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

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

Ответ 3

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

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

Ответ 4

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

Например:

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

Ответ 5

Скопировать из 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 in scope in a method argument list (not just the method 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}

Ответ 6

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

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
                                     ^

Ответ 7

Хмм... Я не могу найти "<: <" в любом месте, но "<:" обозначает подтипирование. Из http://jim-mcbeath.blogspot.com/2008/09/scala-syntax-primer.html#types:

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

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