В Scala можно получить «Val», на который ссылается тип синглтона?
-
27-10-2019 - |
Вопрос
Я пытаюсь получить минимальную форму зависимых типов в Scala. Если у меня есть
class A[T <: Int]
val x: Int = 7
Я могу
val a = new A[x.type]
Теперь можно восстановиться x
от его синглтона x.type
?
Или, если это невозможно, возможно ли как -то связать стабильный идентификатор с типом, а затем извлечь его?
Решение
Нет, ты не можешь выздороветь x
из x.type
Из -за стирания типа JVM. Например, как это будет реализовано?
def f[A]: A = ???
f[x.type]
На уровне байт -кодов JVM нет никакого способа f
может найти ценность x: A
данный A = x.type
Потому что ему нечего работать: все параметры типа теряются во время выполнения, и в любом случае, x
ценность недоступна на f
Степень параметров.
По той же причине, чтобы получить стабильный идентификатор типа, вам придется переоценить его как Manifest
ценность. Но когда я попробовал, я получу странный результат,
def f[A : Manifest] = implicitly[Manifest[A]]
val x = "hi"
val y = "ho"
println(f[x.type]) // hi.type
println(f[y.type]) // ho.type
f[x.type] == f[y.type] // true !?
Я не уверен, почему эти два типа манифеста равны --- у них даже разные toString
представления. Может ли это быть ошибкой Scala? Обновлять: Согласно Scaladoc, Операторы типового режима <: <и =: = = должны рассматриваться только приближения, поскольку существуют множество аспектов соответствия типа, которые еще не представлены в манифестах.
Подводя итог, повторение информации о типе в значениях времени выполнения не происходит автоматически на JVM. Скала Manifest
Предполагается заполнить разрыв, но я думаю, что он не работает с зависимыми типами.
Другие советы
Чтобы ответить на ваш второй вопрос «связывать стабильный идентификатор с типом», один из способов сделать это - использовать классы типов. Допустим, я хочу связать описание строки с типами, я могу сделать это следующим образом:
trait Tag[A] {
val desc : String
}
implicit object StringTag extends Tag[String] {
val desc = "character string"
}
implicit object IntTag extends Tag[Int] {
val desc = "32-bit integer"
}
Теперь, чтобы восстановить такие теги, введите неявную магию:
def printTag[T : Tag] {
val tag = implicitly[Tag[T]]
println("Type is described as : " + tag.desc)
}
Например:
printTag[String] // prints "Type is described as : character string"
printTag[Double] // compile-time error: no implicit value found of type Tag[Double]
Вы можете даже генерировать теги по мере необходимости, используя неявные функции. Например:
implicit def liftTagToList[T : Tag] = new Tag[List[T]] {
val underlying = implicitly[Tag[T]].desc
val desc = "list of " + underlying + "s"
}
Теперь я могу сделать следующее:
// prints "Type is described as : list of character strings"
printTag[List[String]]
и даже:
// prints "Type is described as : list of list of character stringss"
printTag[List[List[String]]]
Пожалуйста, простите плюрализацию.