Scala &引用;结构精化中的参数类型不能引用在该精化之外定义的抽象类型;

Scala &引用;结构精化中的参数类型不能引用在该精化之外定义的抽象类型;,scala,Scala,当我编译时: object Test extends App { implicit def pimp[V](xs: Seq[V]) = new { def dummy(x: V) = x } }

当我编译时:

object Test extends App {
  implicit def pimp[V](xs: Seq[V]) = new {
    def dummy(x: V) = x
  }
}                                                                                                                                                                                                              
我得到:

$ fsc -d aoeu go.scala
go.scala:3: error: Parameter type in structural refinement may not refer to an abstract type defined outside that refinement
    def dummy(x: V) = x
        ^
one error found
为什么?


(并没有真正回答这个问题。)

在发布此消息后不久就发现了问题:我必须定义一个命名类,而不是使用匿名类。(不过,我还是希望能听到更好的解释。)


有效。

规范不允许使用。参见3.2.7化合物类型

在结构元素中的方法声明中,任何值参数的类型只能指元素中包含的类型参数或抽象类型。也就是说,它必须引用方法的类型参数 本身,或企业内部的类型定义。此限制不适用 函数的结果类型

在修复之前,编译器会编译这个,并且您会得到一个在运行时找不到的方法。这是固定的,这就是为什么你得到这个美妙的信息

那么,问题是,为什么不允许这样做

这是2007年scala邮件列表中Gilles Dubochet的一篇文章。这大致归结为这样一个事实:结构类型使用反射,如果它使用在细化之外定义的类型,编译器不知道如何查找要调用的方法(编译器不知道如何提前填充
p.getClass.getMethod(“pimp”,Array(?))

但是去看看这篇文章,它会回答你的问题和更多的问题

编辑:

你好名单

我尝试在函数中用抽象数据类型定义结构类型 有什么原因吗

我听说了两个关于结构类型的问题 Scala 2.6最近的扩展,我想在这里回答

  • 为什么我们要改变Scala的原生值(“int”等)装箱方案 到Java的(“Java.lang.Integer”)
  • 为什么在结构上定义了对参数的限制 方法(“结构细化中的参数类型”不能引用 要抽象在同一细化之外定义的类型,则需要
  • 在回答这两个问题之前,我需要先谈谈 结构类型的实现

    JVM的类型系统非常基本(对应于Java1.4) 这意味着许多可以在Scala中表示的类型不能 在VM.Path依赖类型(“x.y.A”)中表示,单例类型 (“a.type”)、复合类型(“a和B”)或抽象类型都是类型 无法在JVM的类型系统中表示

    为了能够编译成JVM字节码,Scala编译器更改了 Scala将程序类型更改为“擦除”(参见本手册第3.6节) 已擦除的类型可以在VM的类型系统和 在程序上定义一个类型规程,该规程与 该程序使用Scala类型(保存一些强制转换)进行类型化,尽管更少 精确。作为旁注,类型在VM中被擦除的事实 解释为什么要对类型(模式)的动态表示进行操作 类型匹配)对于Scala的类型非常有限 系统

    到目前为止,Scala中的所有类型构造都可以以某种方式擦除。 对于结构类型,情况并非如此。简单结构类型“{def 无法将x:Int}”擦除为“Object”,因为VM不允许 访问“x”字段。使用接口“interface x{int x{};}” 因为被擦除的类型也不起作用,因为任何实例都被 此类型的值必须实现不能 在单独汇编的情况下完成。确实(请容忍)任何 类,该类包含与中定义的成员同名的成员 任何地方的结构类型都必须实现相应的 不幸的是,这个类甚至可能在 已知存在结构类型

    而是实现对结构定义的成员的任何引用 作为反射调用,完全绕过VM的类型系统 示例
    def(p:{defx(q:Int):Int})=p.x(4)
    将被重写 例如:

      def f(p: Object) = p.getClass.getMethod("x", Array(Int)).invoke(p, Array(4))
    
    现在是答案

  • 每当 调用的方法使用本机值(“int”) 调用必须看起来像“…调用(p,数组(new java.lang.Integer(4)).intValue”
  • Scala程序中的整数值通常已装箱(以允许 “Any”类型),并且将它们从Scala自己的文件中拆开是浪费的 装箱方案,立即将它们重新装箱为java.lang.Integer

    更糟糕的是,当反射呼叫具有“任意”返回类型时, 返回java.lang.Integer时应该做什么?调用 方法可能返回一个“int”(在这种情况下应该是 取消绑定并作为Scala框重新绑定),或者它可能返回 应保持不变的java.lang.Integer

    相反,我们决定将Scala自己的装箱方案改为Java 前面的两个问题随后就消失了。有些问题与性能有关 我们对Scala拳击方案进行了优化(预先计算 最常见数字的盒装形式)易于与Java一起使用 最后,使用Java boxing甚至比 我们自己的计划

  • “getMethod”的第二个参数是类型为 要查找的(结构定义的)方法的参数 选择名称重载时要获取的方法。这是 一个在执行过程中需要精确静态类型的地方 转换结构成员调用。通常是可利用的静态类型 方法的参数随结构类型一起提供 定义。在上面的示例中,“x”的参数类型为 为“Int”,允许查找它
  • 参数类型定义为抽象类型,其中
      def f(p: Object) = p.getClass.getMethod("x", Array(Int)).invoke(p, Array(4))