Пусть X
будет конструктором типа с параметрами типа A1
, A2
, ..., An
. Например Option[A]
и Function1[A1, A2]
.
Пусть X[T1, T2, ..., Tn]
будет типом, полученным в результате применения конструктора типа X
к конкретному аргументу типа T1
, T2
, ... Tn
. Например Option[Int]
и Function1[Long, List[String]]
.
Пусть Y
будет прямым подклассом X
, который оставляет некоторые параметры типа X
нефиксированными, не добавляет новый параметр свободного типа, а его параметры типа B1
, B2
,..., Bm
с m <= n
. Например Some[B]
и PartialFunction[B1, B2]
.
Мне нужно реализовать функцию, которая находит конкретные типы R1
, R2
,..., Rm
для присвоения параметрам типа B1
, B2
,..., Bm
конструктора типа Y
таким образом, что Y[R1, R2, ..., Rm] <:< X[T1, T2, ..., Tn]
со всеми удаленными вариантами (все признаки и классы считаются невариантными).
В случае Option
и Some
ясно, что R1 = T1
для Some[R1] <:< Option[T1]
с удаленной дисперсией будет истинным. Кроме того, в случае Function1
и PartialFunction
ясно, что R1 = T1
и R2 = T2
для PartialFunction[R1, R2] <:< Function[T1, T2]
с удаленной дисперсией верны. А вот для общего случая несколько сложнее.
Учитывая, что и компилятор, и оператор <:<
библиотеки отражения должны решить эту проблему, чтобы проверить присваиваемость; Я предполагаю, что функция API отражения уже решает мою проблему. Но я не нахожу. Y полагаю, что это def asSeenFrom(pre: Type, clazz: Symbol): Type
, но я пробовал безрезультатно. Наверняка, я что-то делаю не так.
Это пример использования функции, которая отвечает на этот вопрос:
import scala.reflect.runtime.universe._
val optionOfInt: Type = typeOf[Option[Int]]
val someTypeConstructor: ClassSymbol = typeOf[Some[_]].typeSymbol.asClass
val someOfInt: Type = instantiateSubclassTypeConstructor(optionOfInt, someTypeConstructor)
print(someOfInt.typeArgs) // outputs "List(Int)"
Где instantiateSubclassTypeConstructor
— функция, отвечающая на этот вопрос.
/** @param baseInstantiation a class constructor instantiation. For example: {{{typeOf[Option[Int]]}}}
* @param directSubclassSymbol the [[ClassSymbol] of the class constructor we want to instantiate such that it is assignable to `baseInstantiantion`. For example: {{{typeOf[Some[_]].typeSymbol.asClass}}}
* @return a type instantiation of the class constructor referenced by the `directSubclassSymbol` such that it is assignable to `baseInstantiantion`. For example: {{{typeOf[Some[Int]]}}}
*/
def instantiateSubclassTypeConstructor(baseInstantiation: Type, directSubclassSymbol: ClassSymbol): Type = ???
Скала версия: 2.13.3
it is clear that R1 = T1 for Some[R1] <:< Option[T1]
это правда? Я думаю, чтоSome[R1] <:< Option[T1]
если и только еслиR1 <:< T1
. А вы знаете о стирании шрифта? Я считаю, что то, что вы пытаетесь решить, не может быть решено для общего случая. Только для некоторых очень специфических случаев, когда определения типов сохраняются во время компиляции. - person SimY4   schedule 24.10.2020def asSeenFrom(pre: Type, clazz: Symbol): Type
, определенного вscala.reflect.api.Types
. Видимо решает эту проблему. Но я не могу понять, как его использовать. Пример в документе устарел, поскольку в нем используетсяThisType
, который был удален из API. - person Readren   schedule 24.10.2020internal.thisType(C)
вместоThisType(C)
. - person Dmytro Mitin   schedule 24.10.2020