【问题标题】:How do you 'foreach' over a list of types in Scala, using the iterated value as a type parameter?您如何使用迭代值作为类型参数来“遍历”Scala 中的类型列表?
【发布时间】:2020-05-05 01:49:22
【问题描述】:

我需要构造一个大的HashMap,但是我不想手动将每个值输入到map中,这里是一个例子。

val codecs = HashMap(
    "Foo" -> deriveEncoder[Foo],
    "Bar" -> deriveEncoder[Bar],
    "Qux" -> deriveEncoder[Qux],
  )

deriveEncoder 是一个接受单个类型参数的函数。理想情况下,我想要以下内容:

val concreteClasses = List(Foo, Bar, Qux)
concreteClasses.foreach(T => codecs.put(T.name, deriveEncoder[T]))

这是不可能的,但什么是合理的替代方案?

原因还在于它允许在对象构造期间传入类型列表,从而将实际类型与包含类本身的实现解耦。

谢谢

【问题讨论】:

  • deriveEncoder的定义是什么?
  • @Dima 在 Circe 图书馆。 final def derivedEncoder[A](隐式编码: Lazy[DerivedAsObjectEncoder[A]]): Encoder.AsObject[A] = encode.value
  • 你有什么理由想要编解码器的地图吗?

标签: scala foreach types implicit


【解决方案1】:

目标是在运行时动态构造HashMap,其中键是类型,但类型是编译时构造。 TypeTag 是一种将编译时类型信息传输到运行时的方法。也许这样的事情是可能的

package example

import scala.collection.immutable.HashMap
import scala.reflect.runtime.universe
import scala.tools.reflect.ToolBox
import scala.reflect.runtime.universe._

case class Foo(i: Int)
case class Bar(i: Int)
case class Qux(i: Int)

trait Encoder[T] {
  def encode(v: T): String
}

object Encoder {
  def apply[T](implicit ev: Encoder[T]) = ev
  implicit val fooEncoder: Encoder[Foo] = v => v.toString
  implicit val barEncoder: Encoder[Bar] = v => v.toString
  implicit val quxEncoder: Encoder[Qux] = v => v.toString
}

object forEachOnTypes extends App {
  val concreteClasses = List(typeTag[Foo], typeTag[Bar], typeTag[Qux])

  def encodersFor(tps: List[TypeTag[_]]) = {
    val toolbox = universe.runtimeMirror(Thread.currentThread().getContextClassLoader).mkToolBox()
    tps.map { tp =>
      tp.tpe.typeSymbol.name.toString -> toolbox.eval(toolbox.parse(s"""example.Encoder[${tp.tpe}]""")).asInstanceOf[Encoder[_]]
    }.to(HashMap)
  }

  val encoders = encodersFor(concreteClasses)
  encoders("Foo")
}

但是我不知道这是否合理,因为我们必须使用asInstanceOf

encoders("Foo").asInstanceOf[Encoder[Foo]].encode(Foo(42))

【讨论】:

    猜你喜欢
    • 2013-06-13
    • 1970-01-01
    • 1970-01-01
    • 2020-10-31
    • 2016-12-05
    • 2013-05-24
    • 2014-12-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多