键入 Class 具有上下文绑定的隐式
Type Class Implicits with Context Bound
我正在慢慢自学 Scala 类型 classes。假设我有以下示例:
object Example extends App {
trait Serializer[T] {
def serialize(seq: Seq[T]): String
}
object Serializer {
def serialize[T](seq: Seq[T])(implicit serializer: Serializer[T]): Value = serializer.serialize(seq)
}
implicit object StringSerializer extends Serializer[String] {
def serialize(seq: Seq[String]): String = seq.toString()
}
implicit object IntSerializer extends Serializer[Int] {
def serialize(seq: Seq[Int]): String = seq.toString()
}
case class Data[T: Serializer](x: Seq[T], y: Seq[T], z: Seq[T]) {
val series = Data.createString(x, y, z)
}
object Data {
def createString[T : Serializer](x: Seq[T], y: Seq[T], z: Seq[T]) = {
val serialize = implicitly[Serializer[T]]
List(serialize.serialize(x), serialize.serialize(y))
}
}
val x = Seq("a", "b", "c")
val y = Seq(1, 2, 3, 4)
val z = Seq(10, 20, 30)
val data = Data(x, y, z)
println(data.series)
}
现在失败了
could not find implicit value for evidence parameter of type
Example.Serializer[Any] [error] val data = Data(x, y, z)
有人可以指导我如何使 createString
方法起作用吗?根据我的理解,因为我有一个 Seq[Int]
和一个 Seq[String]
,类型 [T]
将被推断为 [Any]
,这会导致问题。
但是,我根据我的 Serializer
类型 class 放置了一个上下文绑定,我认为这会让编译器寻找 String
或 Int
序列化程序,它做不到。我基本上想传递我有定义的序列化器的任何序列,所以在这个 Seq[Int]
和 Seq[String]
.
的任意组合中
任何指导将不胜感激!
如果您希望 Data
的字段是 Seq
不同元素类型的字段,请执行此操作
case class Data[T: Serializer, T1: Serializer, T2: Serializer](x: Seq[T], y: Seq[T1], z: Seq[T2]) {
val series = Data.createString(x, y, z)
}
object Data {
def createString[T : Serializer, T1 : Serializer, T2 : Serializer](x: Seq[T], y: Seq[T1], z: Seq[T2]) = {
val serialize = implicitly[Serializer[T]]
val serialize1 = implicitly[Serializer[T1]]
val serialize2 = implicitly[Serializer[T2]]
List(serialize.serialize(x), serialize1.serialize(y), serialize2.serialize(z))
}
}
同样的问题是您想要不同的类型,但您使用的是单个类型参数 T
;所以编译器推断出任何。
也许您想这样定义 class:
final case class Data[A: Serializer, B: Serializer, C: Serializer](x: Seq[A], y: Seq[B], z: Seq[C])
所以你可以拥有三种不同的类型。
顺便说一句,我建议你使用 List 或 Vector 或 ArraySeq,即具体集合,而不是抽象 Seq.
我正在慢慢自学 Scala 类型 classes。假设我有以下示例:
object Example extends App {
trait Serializer[T] {
def serialize(seq: Seq[T]): String
}
object Serializer {
def serialize[T](seq: Seq[T])(implicit serializer: Serializer[T]): Value = serializer.serialize(seq)
}
implicit object StringSerializer extends Serializer[String] {
def serialize(seq: Seq[String]): String = seq.toString()
}
implicit object IntSerializer extends Serializer[Int] {
def serialize(seq: Seq[Int]): String = seq.toString()
}
case class Data[T: Serializer](x: Seq[T], y: Seq[T], z: Seq[T]) {
val series = Data.createString(x, y, z)
}
object Data {
def createString[T : Serializer](x: Seq[T], y: Seq[T], z: Seq[T]) = {
val serialize = implicitly[Serializer[T]]
List(serialize.serialize(x), serialize.serialize(y))
}
}
val x = Seq("a", "b", "c")
val y = Seq(1, 2, 3, 4)
val z = Seq(10, 20, 30)
val data = Data(x, y, z)
println(data.series)
}
现在失败了
could not find implicit value for evidence parameter of type Example.Serializer[Any] [error] val data = Data(x, y, z)
有人可以指导我如何使 createString
方法起作用吗?根据我的理解,因为我有一个 Seq[Int]
和一个 Seq[String]
,类型 [T]
将被推断为 [Any]
,这会导致问题。
但是,我根据我的 Serializer
类型 class 放置了一个上下文绑定,我认为这会让编译器寻找 String
或 Int
序列化程序,它做不到。我基本上想传递我有定义的序列化器的任何序列,所以在这个 Seq[Int]
和 Seq[String]
.
任何指导将不胜感激!
如果您希望 Data
的字段是 Seq
不同元素类型的字段,请执行此操作
case class Data[T: Serializer, T1: Serializer, T2: Serializer](x: Seq[T], y: Seq[T1], z: Seq[T2]) {
val series = Data.createString(x, y, z)
}
object Data {
def createString[T : Serializer, T1 : Serializer, T2 : Serializer](x: Seq[T], y: Seq[T1], z: Seq[T2]) = {
val serialize = implicitly[Serializer[T]]
val serialize1 = implicitly[Serializer[T1]]
val serialize2 = implicitly[Serializer[T2]]
List(serialize.serialize(x), serialize1.serialize(y), serialize2.serialize(z))
}
}
同样的问题是您想要不同的类型,但您使用的是单个类型参数 T
;所以编译器推断出任何。
也许您想这样定义 class:
final case class Data[A: Serializer, B: Serializer, C: Serializer](x: Seq[A], y: Seq[B], z: Seq[C])
所以你可以拥有三种不同的类型。
顺便说一句,我建议你使用 List 或 Vector 或 ArraySeq,即具体集合,而不是抽象 Seq.