使用结构类型时出现意外错误

时间:2018-07-20 18:31:21

标签: arrays scala types structural-typing

我是Scala编程的新手,所以如果这是一个愚蠢的问题,请多多包涵。由于a有一个mkString方法,我期望下面的代码能工作。

val a = "abc".toCharArray

case class A[T: {def mkString(): String}](i: T) {
  val s = i.mkString
}

A(a)

但是会出现以下错误:

  

错误:(3,16)AnyRef {def mkString():String}没有采用类型   参数案例类A [T:{def mkString():String}](i:T)

     

错误:(4,14)值mkString不是类型参数T val的成员   s = i.mkString

我正在使用Scala 2.11.6。

任何帮助将不胜感激!谢谢!

2 个答案:

答案 0 :(得分:2)

类型边界[A : B]是表示存在类型B的类型类A实例的一种简写方式,因此它们是等效的:

def foo[A : B]: C

def foo[A](implicit b: B[A]): C

您可能正在寻找的语法是[A <: B],这意味着A必须是B的子类。

但是随后您遇到的问题是mkString实际上不在Array类中;如文档中所述,它是在ArrayOps中定义的(从Array起隐式转换):

  

此成员通过从Array [T]隐式转换为   ArrayOps [T]由scala.Predef中的genericArrayOps方法执行。

您可以通过以下方法解决此问题:

val a = "abc".toCharArray

case class A[T](i: T)(implicit conv: T => {def mkString: String}) {
  val s = conv(i).mkString
}

A(a)

答案 1 :(得分:1)

那里至少有三个错误:

  1. 应为<:,而不是:。结构类型不是类型类。
  2. def mkString(): Stringdef mkString: String不同。
  3. 原始JVM数组对诸如mkString之类的方便Scala方法一无所知。为此,您需要一个WrappedArray

这在这里有效:

import scala.language.reflectiveCalls
val a = "abc".toCharArray

import collection.mutable.WrappedArray

case class A[T <: { def mkString: String }](i: T){
  val s = i.mkString
}

A(a: WrappedArray[Char])