用于复合材料的 Scala Typeclass

Scala Typeclass for composites

我有求和类型,映射:

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] 的一个实例。有没有办法告诉编译器它应该使用范围内的任何类型类实例?

类型系统正在寻找 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)
    }
}

或者,让您的平面图执行匹配逻辑:

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)
    }
  }