加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Scala更高级的类型和协变

发布时间:2020-12-16 09:51:12 所属栏目:安全 来源:网络整理
导读:我试图抽象出一些可以返回A,Option [A]或Seq [A]类型的库API. 到目前为止,我有这样的事情: type Const[T] = T sealed abstract class Request[F[_],A] case class GetOne(id: Int) extends Request[Const,Int] case class GetMany() extends Request[Seq,St
我试图抽象出一些可以返回A,Option [A]或Seq [A]类型的库API.

到目前为止,我有这样的事情:

type Const[T] = T

  sealed abstract class Request[F[_],A]

  case class GetOne(id: Int) extends Request[Const,Int]
  case class GetMany() extends Request[Seq,String]

然后当我使用它时:

def get[F[_],A](request: Request[F,A]): F[A] = request match {
  case GetOne(id) => client.getOne[F[A]](id)
  case GetMany() => client.getMany[A]() // error: Seq[A] does not conform to F[A]
}

我理解为什么这不起作用,因为F [_]不是协变Seq [_]的子类或类似的东西.但是我不知道如何在能够使用Const [A]的情况下解决这个问题.我绝望了吗?请帮忙.

解决方法

对于这种类型的多态,您可以使用类型类概念
考虑到

trait Client {
  def getOne[X]: X
  def getMany[X]: Seq[X]
}

type Const[T] = T

sealed abstract class Request[F[_],A]

case class GetOne(id: Int) extends Request[Const,Int]
case class GetMany() extends Request[Seq,String]

我们可以定义这样的类型类:

trait HandleRequest[R <: Request[F,A],F[_],A] {
  def apply(request: R,client: Client): F[A]
}

并针对所需案例进行实例化:

implicit object handleGetOne extends HandleRequest[GetOne,Const,Int] {
  def apply(request: GetOne,client: Client): Int = client.getOne
}

implicit object handleGetMany extends HandleRequest[GetMany,Seq,String] {
  def apply(request: GetMany,client: Client): Seq[String] = client.getMany
}

现在您可以按如下方式定义常规函数:

implicit class ClientOps(val client: Client) {
  def get[R <: Request[F,A](request: R)(implicit handle: HandleRequest[R,F,A]): F[A] =
    handle(request,client)
}

如果您想要概括您的请求类型,例如:

case class GetOne[X](id: Int) extends Request[Const,X]
case class GetMany[X]() extends Request[Seq,X]

您可以将实例重新定义为:

implicit def handleGetOne[X] = new HandleRequest[GetOne[X],X] {
  def apply(request: GetOne[X],client: Client): X = client.getOne
}

implicit def handleGetMany[X] = new HandleRequest[GetMany[X],X] {
  def apply(request: GetMany[X],client: Client): Seq[X] = client.getMany
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读