Может ли кто-нибудь предоставить некоторые сведения о операторе <:<
в scala.
Я думаю:
if(apple <:< fruit) //checks if apple is a subclass of fruit.
Есть ли другие объяснения? Я вижу много определений в исходном файле scala.
Может ли кто-нибудь предоставить некоторые сведения о операторе <:<
в scala.
Я думаю:
if(apple <:< fruit) //checks if apple is a subclass of fruit.
Есть ли другие объяснения? Я вижу много определений в исходном файле scala.
<:<
не оператор - он является идентификатором и поэтому является одним из:
В этом случае <:<
появляется дважды в библиотеке, один раз в Predef
как класс и один раз как метод на Manifest
.
Для метода на Manifest
он проверяет, является ли тип, представленный этим манифестом, подтипом, представленным аргументом манифеста.
Для типа в Predef
это относительно новое, и я тоже немного смущен, потому что он, кажется, является частью триумвирата идентичных объявлений!
class <%<[-From, +To] extends (From) ⇒ To
class <:<[-From, +To] extends (From) ⇒ To
class =:=[From, To] extends (From) ⇒ To
Тип <:<
определяется в 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, но не могу найти его в данный момент.
Я спросил, и это объяснение, которое я получил:
<:<
обычно используется как параметр доказательства. Например, в TraversableOnce
, toMap
объявляется как def toMap[T, U](implicit ev: A <:< (T, U)): immutable.Map[T, U]
. Это выражает ограничение того, что метод toMap
работает только в том случае, если в прохождении содержится 2-кортежи. flatten
- еще один пример. <:<
используется для выражения ограничения, что вы можете только сгладить обходные трассировки.
Собственно, он проверяет, является ли класс, представленный Manifest
яблоком, подклассом класса, представленного манифестным плодом.
Например:
manifest[java.util.List[String]] <:< manifest[java.util.ArrayList[String]] == false
manifest[java.util.ArrayList[String]] <:< manifest[java.util.List[String]] == true
Скопировать из 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}
Чтобы лучше понять реализация.
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
^
Хмм... Я не могу найти "<: <" в любом месте, но "<:" обозначает подтипирование. Из http://jim-mcbeath.blogspot.com/2008/09/scala-syntax-primer.html#types:
List[T] forSome { type T <: Component }
В приведенном выше примере мы говорим, что T - это некоторый тип, который является подтипом Component.