Reputation: 3358
I'm new to Scala programming, so please bear with me if it's a silly question. I was expecting the following code to work, since a
has a mkString
method.
val a = "abc".toCharArray
case class A[T: {def mkString(): String}](i: T) {
val s = i.mkString
}
A(a)
But it gives the following error:
Error:(3, 16) AnyRef{def mkString(): String} does not take type parameters case class A[T: {def mkString(): String}](i: T)
Error:(4, 14) value mkString is not a member of type parameter T val s = i.mkString
I'm using Scala 2.11.6.
Any help will be really appreciated! Thank you !
Upvotes: 2
Views: 151
Reputation: 44908
At least three mistakes there:
<:
, not :
. The structural type is not a typeclass.def mkString(): String
is not the same as def mkString: String
.mkString
. You need a WrappedArray
for that.This here works:
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])
Upvotes: 1
Reputation: 18424
The type bounds [A : B]
is a shorthand way of saying there exists an instance of the typeclass B
for type A
, so these are equivalent:
def foo[A : B]: C
def foo[A](implicit b: B[A]): C
The syntax you're probably looking for is [A <: B]
, which means A
must be a subclass of B
.
But then you have the issue that mkString
isn't actually in the Array
class; it's defined in ArrayOps
(with an implicit conversion from Array
) as described in the documentation:
This member is added by an implicit conversion from Array[T] to ArrayOps[T] performed by method genericArrayOps in scala.Predef.
You can work around that with:
val a = "abc".toCharArray
case class A[T](i: T)(implicit conv: T => {def mkString: String}) {
val s = conv(i).mkString
}
A(a)
Upvotes: 2