簡體   English   中英

Scala發散隱式擴展

[英]Scala diverging implicit expansion

我想為通用enumeratum.values.ValueEnumEntry [ValueType]編寫一個anorm.ToStatement實例。 但是似乎ValueType不能正確推斷。

我的代碼:

import java.sql.PreparedStatement
import anorm._
import enumeratum.values._

sealed trait Test extends IntEnumEntry
object Test extends IntEnum[Test] {
  case object One extends Test {val value = 1}
  val values = findValues
}

implicit def valueEnumEntryToStatement[ValueType: ToStatement, A <: ValueEnumEntry[ValueType]]: ToStatement[A] =
  (s: PreparedStatement, index: Int, v: A) => implicitly[ToStatement[ValueType]].set(s, index, v.value)

val toStatement: ToStatement[Test] = implicitly[ToStatement[Test]] //NOT OK: diverging implicit expansion for type anorm.ToStatement[ValueType]

對於類型為anorm.ToStatement [ValueType]的隱式擴展,它失敗。

但是,如果我顯式設置了Int類型,它將起作用。

//either
implicit def valueEnumEntryToStatement[A <: ValueEnumEntry[Int]]: ToStatement[A] =
  (s: PreparedStatement, index: Int, v: A) => implicitly[ToStatement[Int]].set(s, index, v.value)

val toStatement: ToStatement[Test] = implicitly[ToStatement[Test]] //OK
//or
def valueEnumEntryToStatement[ValueType: ToStatement, A <: ValueEnumEntry[ValueType]]: ToStatement[A] =
  (s: PreparedStatement, index: Int, v: A) => implicitly[ToStatement[ValueType]].set(s, index, v.value)
implicit def intEnumEntryToStatement[A <: IntEnumEntry]: ToStatement[A] = valueEnumEntryToStatement[Int, A]

val toStatement: ToStatement[Test] = implicitly[ToStatement[Test]]

有沒有一種方法可以在不顯式設置類型的情況下提供通用解決方案?

問題在於ValueType是特征ValueEnumEntry的類型參數,並且那里沒有類型成員ValueType (因此我們不能使用類型Test#ValueType )。 嘗試定義類型類

  import java.sql.PreparedStatement
  import anorm._
  import enumeratum.values._

  sealed trait Test extends IntEnumEntry
  object Test extends IntEnum[Test] {
    case object One extends Test {val value = 1}
    val values = findValues
  }

  trait ValueEnumValueType[EntryType <: ValueEnumEntry[_]] {
    type ValueType
  }
  object ValueEnumValueType {
    type Aux[EntryType <: ValueEnumEntry[_], VT] = ValueEnumValueType[EntryType] { type ValueType = VT }
    implicit def byte[A <: ByteEnumEntry]    : Aux[A, Byte]   = null
    implicit def char[A <: CharEnumEntry]    : Aux[A, Char]   = null
    implicit def int[A <: IntEnumEntry]      : Aux[A, Int]    = null
    implicit def long[A <: LongEnumEntry]    : Aux[A, Long]   = null
    implicit def short[A <: ShortEnumEntry]  : Aux[A, Short]  = null
    implicit def string[A <: StringEnumEntry]: Aux[A, String] = null
  }

  implicit def valueEnumEntryToStatement[ValueType, A <: ValueEnumEntry[ValueType]](implicit
    enumValueType: ValueEnumValueType.Aux[A, ValueType],
    toStatement: ToStatement[ValueType]): ToStatement[A] =
    (s: PreparedStatement, index: Int, v: A) => toStatement.set(s, index, v.value)

  val toStatement: ToStatement[Test] = implicitly[ToStatement[Test]]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM