Scala,非常相似类型的抽象逻辑

时间:2017-07-26 14:53:20

标签: scala higher-kinded-types

我觉得我可以进一步抽象我的代码,但我有点卡住了。我这样做更像是一个挑战,所以不要担心过早优化。这是我的开源库Reactive Kraken

如果你看一下这段代码,我相信你会理解我的意思。

case class Response[T](error: List[String], result: Option[Map[String, T]])
case class OrderResponse[T](error: List[String], result: Option[T])

def handleRequest[T: JsonFormat](request: HttpRequest): Future[Response[T]] =
  fireRequest(request)
    .map(_.parseJson.convertTo[Response[T]])
    .recover { case t: Throwable => Response[T](List(t.getMessage), None) }

def handleOrderRequest[A: JsonFormat](request: HttpRequest): Future[OrderResponse[A]] =
  fireRequest(request)
    .map(_.parseJson.convertTo[OrderResponse[A]])
    .recover { case t: Throwable => OrderResponse[A](List(t.getMessage), None) }

这两个函数之间的区别仅仅是它们返回的类型。你会怎么做?也许使用更高 kinded类型?

2 个答案:

答案 0 :(得分:1)

一种方法是统一ResponseOrderResponse

case class Response[T]     (error: List[String], result: Option[Map[String, T]])
case class OrderResponse[T](error: List[String], result: Option[T])
// ===
type Response[T] = OrderResponse[Map[String, T]]
case class OrderResponse[T](error: List[String], result: Option[T])

然后OrderResponse上的函数也是Response上的函数。但是,我不知道这些类型的语义。

如果不满意,类型类将会:

trait Recovering[T] {
  def recover(error: Throwable): T
}
object Recovering {
  def apply[T: Recovering] = implicitly[Recovering[T]]
}

implicit def requestsAreRecovering[T]: Recovering[Request[T]] = new Recovering[Request[T]] {
  override def recover(error: Throwable) = Request[T](List(t.getMessage), None)
}
implicit def orderRequestsAreRecovering[T]: Recovering[OrderRequest[T]] = new Recovering[OrderRequest[T]] {
  override def recover(error: Throwable) = OrderRequest[T](List(t.getMessage), None)
}

def handleRequest[T: JsonFormat: Recovering](request: HttpRequest): Future[T] =
  fireRequest(request)
    .map(_.parseJson.convertTo[T])
    .recover(Recovering[T].recover)

答案 1 :(得分:1)

如果没有抽象,您仍然可以对代码进行分解:

case class Response[T](error: List[String], result: Option[Map[String, T]])

case class OrderResponse[T](error: List[String], result: Option[T])

private def handle[T: JsonFormat, U](request: HttpRequest, recovery: Throwable => U): Future[U] = {
  fireRequest(request)
    .map(_.parseJson.convertTo[U])
    .recover { case t: Throwable => recovery(t) }
}

def handleRequest[T: JsonFormat](request: HttpRequest): Future[Response[T]] =
    handle(request, {t: Throwable => Response[T](List(t.getMessage), None)})

def handleOrderRequest[T: JsonFormat](request: HttpRequest): Future[Response[T]] =
    handle(request, {t: Throwable => OrderResponse[A](List(t.getMessage), None)})