Scala:如何避免复制粘贴隐式参数?例如类型替代?

时间:2016-12-08 15:54:58

标签: scala typeclass shapeless implicits

这个问题是问题How to define an abstract copyable superclass for any case class的结果,但人们可以单独留下这个背景,并专注于此:

注意:可以在github play-authenticate-usage-scala

中访问整个编译代码库(使用Scala 2.11.8)

我有一个使用shapeless的特性并被定义为(注意implicit mkLens):

import shapeless._, tag.@@
import shapeless._
import tag.$at$at

trait AutoIncEntity[PK, E <: AutoIncEntity[PK, E]] extends Entity[PK] { self: E =>
  def copyWithNewId(id : PK)(implicit mkLens: MkFieldLens.Aux[E, Symbol @@ Witness.`"id"`.T, PK]) : E = {
    (lens[E] >> 'id).set(self)(id)
  }
}

所有复杂性基本上都是这样说的:任何案例类(如Slick自动生成的那些行)通过扩展此特征,提供copyWithNewId(id)的基本可重用实现。此方法只是委托给copy(id = id)方法,该方法是生成的案例类编译器,不能抽象出来或“拉出”#34;。例如,通过扩展UserRow AutoIncEntity可以用作构建在AutoIncEntity之上的框架的一部分:

case class UserRow(id: Long, firstName: Option[String] = None, 
                   middleName: Option[String] = None, lastName: Option[String] = None) 
        extends AutoIncEntity[Long, UserRow]

现在我使用AutoIncEntity构建一个插入新记录的通用Dao,同时从数据库中提取用户实体,包括新生成的自动id

abstract class GenericDaoAutoIncImpl[T <: Table[E] with IdentifyableTable[PK], E <: AutoIncEntity[PK, E], PK: BaseColumnType]
    (dbConfigProvider: DatabaseConfigProvider, tableQuery: TableQuery[T]) extends GenericDaoImpl[T, E, PK](dbConfigProvider, tableQuery)
      with GenericDaoAutoInc[T, E, PK] {
  override def createAndFetch(entity: E)(implicit mkLens: MkFieldLens.Aux[E, Symbol @@ Witness.`"id"`.T, PK]): Future[Option[E]] = {
    val insertQuery = tableQuery returning tableQuery.map(_.id) into ((row, id) => row.copyWithNewId(id))
    db.run((insertQuery += entity).flatMap(row => findById(row.id)))
  }
}

现在的问题是如何修改此解决方案以避免传播/复制粘贴&#34; voodoo&#34;隐式参数(implicit mkLens: MkFieldLens.Aux[E, Symbol @@ Witness.&#34; id&#34; .T, PK])?和相应的需要&#34; voodoo&#34;进口?

0 个答案:

没有答案