"不能存在抽象的参数化类型..."

Tom*_*ett 13 scala functor typeclass implicits

我正在搞乱Scala 2.8以获得乐趣,并试图定义一个pimp,它为类型构造函数添加了一个"as"方法,允许从一个仿函数转换为另一个仿函数(请忽略我不一定在这里处理仿函数的事实) .例如,您可以像这样使用它:

val array:Array[T]
val list:List[T] = array.as[List]
Run Code Online (Sandbox Code Playgroud)

所以这就是我试图做的事情:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

然而,定义的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)
Run Code Online (Sandbox Code Playgroud)

它似乎工作.但似乎我的第一次尝试应该是等效的,所以我很好奇为什么它失败了,错误信息意味着什么.

Arj*_*ijl 11

我的预感是,这是因为由于规范中的以下陈述,§6.11,块:

本地定义的类型定义类型t = T由存在子句类型t>:T <:T绑定.如果t携带类型参数则是错误的.

并且结构实例创建表达式被计算为块,所以


new {def greet{println("hello")}}
Run Code Online (Sandbox Code Playgroud)

是一个简写


{ class anon$X extends AnyRef{ def greet = println("hello") }; new anon$X }
Run Code Online (Sandbox Code Playgroud)

所以它评估一个块表达式(根据规范的第6.10节),具有上述限制.然而,为什么这个限制是我不知道的.抛出的错误可以在此位置的Typers类中找到,这似乎确认此限制是您看到的错误的原因.如前所述,在类中编码函数会删除块表达式限制:


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}

Run Code Online (Sandbox Code Playgroud)