Что такое манифест в Scala и когда он вам нужен?



С Scala 2.7.2 есть что-то под названием Manifest который является обходным путем для стирания типа Java. Но как это Manifest работа именно и почему / когда вам нужно использовать его?



в блоге Манифесты: Овеществленные Типы Хорхе Ортис объясняет некоторые из них, но это не объясняет, как использовать его вместе с контексте границ.



кроме того, что такое ClassManifest какая разница с Manifest?



у меня есть некоторый код (часть более крупной программы, не может легко включить его здесь), который имеет некоторые предупреждения в отношении стирания типа; Я подозреваю, что могу решить их с помощью манифестов, но я не уверен точно, как это сделать.

614   4  

4 ответов:

компилятор знает больше информации о типах, чем может легко представить среда выполнения JVM. Манифест-это способ для компилятора отправить межмерное сообщение в код во время выполнения о потерянной информации о типе.

неясно, будет ли Манифест полезен для ошибок, которые вы видите, не зная более подробно.

 def foo[T](x: List[T])(implicit m: Manifest[T]) = {
    if (m <:< manifest[String])
      println("Hey, this list is full of strings")
    else
      println("Non-stringy list")
  }

  foo(List("one", "two")) // Hey, this list is full of strings
  foo(List(1, 2)) // Non-stringy list
  foo(List("one", 2)) // Non-stringy list

решение на основе отражения для этого, вероятно, будет включать проверку каждого элемента списка.

контекстная привязка кажется наиболее подходящей для использования классов типов в scala и хорошо объясняется здесь Debasish Ghosh: http://debasishg.blogspot.com/2010/06/scala-implicits-type-classes-here-i.html

границы контекста также могут просто сделать сигнатуры метода более читаемыми. Например, эта функция может быть переписана используя контекстные границы, например:

  def foo[T: Manifest](x: List[T]) = {
    if (manifest[T] <:< manifest[String])
      println("Hey, this list is full of strings")
    else
      println("Non-stringy list")
  }

не полный ответ, но относительно разницы между Manifest и ClassManifest, вы можете найти пример в Scala 2.8 Array статьи:

единственный оставшийся вопрос - как реализовать создание универсального массива. В отличие от Java, Scala позволяет создавать экземпляр new Array[T] здесь T параметр типа. Как это может быть реализовано, учитывая тот факт, что в Java не существует единого представления массива?

единственный способ сделать это-потребовать дополнительную информацию о времени выполнения, которая описывает тип T. В Scala 2.8 имеет новый механизм для этого, который называется Манифест. Объект типа Manifest[T] предоставляет полную информацию о типе T.
Manifest значения обычно передаются в неявных параметрах; и компилятор знает, как построить их для статически известных типов T.

есть еще слабее форма имени ClassManifest который может быть построен из знания только класса верхнего уровня типа, не обязательно зная все его типы аргументов.
Именно этот тип информации о времени выполнения требуется для создания массива.

пример:

нужно предоставить эту информацию, передав ClassManifest[T] в метод как неявный параметр:

def  tabulate[T](len:Int,  f:Int=>T)(implicit m:ClassManifest[T]) =  { 
  val  xs  =  new  Array[T](len) 
  for   (i  <- 0  until   len)  xs(i)   = f(i) 
  xs 
} 

как a сокращенная форма, контекст bound1 может быть использован для параметра типа T вместо

(см. так вопрос для иллюстрации)

, давая:

def  tabulate[T:    ClassManifest](len:Int,  f:Int=>T)  =  { 
  val  xs  =  new  Array[T](len) 
  for   (i  <- 0  until   len)  xs(i)   = f(i) 
  xs 
} 

при вызове tabulate на тип, такой как Int или String или List[T], компилятор Scala может создать манифест класса для передачи в качестве неявного аргумента для табуляции.

Манифест был предназначен для овеществления универсальных типов, которые стираются для запуска на JVM (который не поддерживает универсальные типы). Однако у них были некоторые серьезные проблемы: они были слишком упрощены и не могли полностью поддерживать систему типов Scala. Они были такими устаревший в Scala 2.10, и заменяются TypeTags (которые по существу являются тем, что сам компилятор Scala использует для представления типов и поэтому полностью поддерживает типы Scala). Для получения более подробной информации о разнице, смотрите:

другими словами

когда вам это нужно?

до 2013-01-04, когда Scala 2.10 был выпущен.

давайте также chck out manifest на scala источники (Manifest.scala), мы видим:

Manifest.scala:
def manifest[T](implicit m: Manifest[T])           = m

Итак, что касается следующего примера кода:

def foo[A](somelist: List[A])(implicit m: Manifest[A]): String = {
  if (m <:< manifest[String]) {
    "its a string"
  } else {
    "its not a string"
  }
}

мы видим, что manifestfunction поиск неявного m: Manifest[T] что соответствует type parameter вы предоставляете в нашем примере кода это было manifest[String]. Поэтому, когда вы называете что-то вроде:

if (m <:< manifest[String]) {

вы проверяете, если ток implicit m который вы определили в своей функции имеет тип manifest[String] и как то manifest является функцией типа manifest[T] он будет искать конкретный manifest[String] и он найдет, если есть такой неявный.

Comments

    Ничего не найдено.