Scala Typeclass用于复合材料

时间:2016-05-23 19:13:50

标签: scala typeclass scala-cats

我有一个总和类型,映射:

sealed trait Mapping
final case class XMapping(a:String)
final case class FallbackMapping(mappings: List[Mapping])

我有一个类型定义如下:

final case class Param(x:String)

trait ParameterLoader[T] {
  def load(mapping:T) : List[Param]
}

有些情况:

object DefaultParameterLoaders {
  implicit val  xParameterLoader= new QueryParameterLoader[XMapping] {
    override def load(mapping: XMapping): List[Param] = List(Param(mapping.a))
  }

  implicit val fallbackParameterLoader = new ParameterLoader[FallbackMapping] {

    override def load(mapping: FallbackMapping): List[Param] =
      mapping.mappings.flatMap(x => ???)

  }
}

我找不到将隐式实例传递给上面的flatMap的方法。我得到的错误是我缺少ParameterLoader [Mapping]的实例。有没有办法告诉编译器它应该使用范围内的任何类型类实例?

1 个答案:

答案 0 :(得分:2)

类型系统专门寻找ParameterLoader[Mapping],这意味着ParameterLoader[XMapping] / ParameterLoader[FallbackMapping]不够具体。您需要提供ParameterLoader[Mapping]。您可以使用现有定义执行此操作。

implicit def mappingLoader(implicit xpLoader: ParameterLoader[XMapping], fmLoader: ParameterLoader[FallbackMapping]) = new ParameterLoader[Mapping] { 
  def load(mapping: Mapping): List[QueryParam] = 
    mapping match {
      case xm: XMapping = xpLoader.load(xm)
      case fm: FallbackMapping => fmLoader.load(fm)
    }
}

或者,让您的flatmap执行匹配逻辑:

implicit def fallbackParameterLoader(implicit xpLoader: ParameterLoader[XMapping]) = new ParameterLoader[FallbackMapping] {
  override def load(mapping: FallbackMapping): List[Param] =
    mapping.mappings.flatMap { 
      case xm: XMapping = xpLoader.load(xm)
      case fm: FallbackMapping => this.load(fm)
    }
  }