如何在Scala中定义类型更高的类型实例? [英] How to define typeclass instance for higher kinded types in Scala?

查看:107
本文介绍了如何在Scala中定义类型更高的类型实例?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Scala中实现了一个可序列化类型的类型类型。对于简单类型很容易

$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ ]
}

隐式对象StringSerializer extends Serializer [String] {
覆盖def toBytes(x:String)= ...
}

//其他简单类型的类似代码

但是我被困在定义一个更高版本的实例类型如Option [T],List [T]等。自然,List [T]只有在T可序列化时才可序列化。但是如何在Scala中表达约束呢?我不成功的尝试:

 隐式对象ListSerializer extends Serializer [List [_]] {
//不会编译
覆盖def toBytes [T:Serializer](a:List [T]):Array [Byte] = ...
}


解决方案

事情是,您在 Serializer [List [_]] 实际上,重写方法可以接受的唯一东西是 List [_] 。方法是以某种方式向序列化程序提供一个具体类型 List [T] 。技巧:

  scala> :粘贴
//进入粘贴模式(ctrl-D完成)
//特性序列化器和隐式对象为简洁起见,前者用x.getBytes

实现隐式def listIsSerializable [T:Serializer]:Serializer [List [T]] =
新串行器[List [T]] {
def toBytes(xs:List [T])= xs.map [Serializer [T]] .toBytes).toArray.flatten
}

//退出粘贴模式,现在解释。

定义的特征序列化器
定义的对象StringSerializer
listIsSerializable:[T](隐式证据$ 1:序列化器[T])序列化器[列表[T]]

scala>隐式地[Serializer [List [String]]] toBytes(List(A,B))
res0:Array [Byte] = Array(65,66)


I'm implementing a typeclass of serializable types in Scala. It's easy for simple types

trait Serializer[T] {
  def toBytes(a: T): Array[Byte]
}

implicit object StringSerializer extends Serializer[String] {
    override def toBytes(x: String) = ...
}

// similar codes for other simple types

But I got stuck in defining an instance for higher kinded types like Option[T], List[T], etc. Naturally, List[T] is serializable only if T is serializable. But how to express the constraint in Scala? My unsuccessful try:

implicit object ListSerializer extends Serializer[List[_]] {
  // won't compile
  override def toBytes[T: Serializer](a: List[T]): Array[Byte] = ...
}

解决方案

The thing is, you are using a existencial in Serializer[List[_]] effectively the only thing that an overriding method can accept then is List[_]. The way is to somehow provide a concrete type List[T] to the serializer. The trick:

scala> :paste
// Entering paste mode (ctrl-D to finish)
// trait Serializer and the implicit object removed for brevity, the former was implemented with x.getBytes

implicit def listIsSerializable[T:Serializer]:Serializer[List[T]] = 
  new Serializer[List[T]] {
    def toBytes(xs:List[T])=xs.map(implicitly[Serializer[T]].toBytes).toArray.flatten   
  }

// Exiting paste mode, now interpreting.

defined trait Serializer
defined object StringSerializer
listIsSerializable: [T](implicit evidence$1: Serializer[T])Serializer[List[T]]

scala> implicitly[Serializer[List[String]]].toBytes(List("A","B"))
res0: Array[Byte] = Array(65, 66)

这篇关于如何在Scala中定义类型更高的类型实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆