«Не может экзистенциально аннотация по сравнению с параметризованным типом ...»

StackOverflow https://stackoverflow.com/questions/3122398

Вопрос

Я возился со Scala 2.8 для удовольствия и пытается определить суперизм который добавляет метод «как», чтобы ввести конструкторы, позволяющие преобразовать от одного функтора в другую (пропустить тот факт, что я не обязательно имел дело с функторами здесь). Так, например, вы могли бы использовать это так:

val array:Array[T]
val list:List[T] = array.as[List]

Так вот то, что я пытался сделать:

object Test {
    abstract class NatTrans[F[_], G[_]] {
        def convert[T](f:F[T]):G[T]
    }

    implicit def array2List:NatTrans[Array, List] = new NatTrans[Array, List] { 
        def convert[T](a:Array[T]) = a.toList
    }

    // this next part gets flagged with an error
    implicit def naturalTransformations[T, F[_]](f:F[T]) = new {
        def as[G[_]](implicit n:NatTrans[F, G]) = n convert f
    }
}

Однако определение naturalTransformations помечен с ошибкой «Не может экзистенциально аннотация по параметризованному типу G [T]». Отказ Чтобы исправить это, я могу переписать naturalTransformations вместе с дополнительным классом Transformable вот так:

class Transformable[T, F[_]](f:F[T]) {
    def as[G[_]](implicit n:NatTrans[F, G]) = n convert f
}

implicit def naturalTransformations[T, F[_]](f:F[T]) = new Transformable[T, F](f)

И это похоже на работу. Но кажется, что моя первая попытка должна была быть эквивалентной, поэтому мне любопытно, почему он не удался и что означает сообщение об ошибке.

Это было полезно?

Решение

Моя догадка будет то, что это потому, что из-за следующих утверждений в спецификации § 6.11, блоки:

Локально определенный тип определения типа T = T связан с помощью экзистенциального типа предложения T>: T <: T. Это ошибка, если T несет параметры типа.

И выражение создания структурных экземпляров оценивается в блок, так


new {def greet{println("hello")}}

это сокращение для


{ class anon$X extends AnyRef{ def greet = println("hello") }; new anon$X }

Таким образом, он оценивает экспрессию блока (согласно § 6.10 спецификации), с вышеупомянутым ограничением. Почему это ограничение там, я не знаю, однако. Ошибка, которая бросается, можно найти в классе типов на Это местоположение, который, похоже, подтверждает, что это ограничение является причиной ошибки, которую вы видите. Как вы упоминали, кодирование функции в классе удаляет ограничение выражения блока:


scala> class N[M[_]]
defined class N

scala> class Q { def as[M[_]](n:N[M]) = null}
defined class Q

scala> new { def as[M[_]](n:N[M]) = null}       
:7: error: can't existentially abstract over parameterized type M
       new { def as[M[_]](n:N[M]) = null}

Другие советы

Для меня это звучит как простота против общего случая.

Также обратите внимание, что наличие класса превращает звонок в быстрое вызование, а не вызывающую так как() метод отражением.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top