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
是 trait ValueEnumEntry
中的类型参数,那里没有类型成员 ValueType
(所以我们不能使用类型 Test#ValueType
).尝试定义类型 class
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]]
我想为泛型 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
是 trait ValueEnumEntry
中的类型参数,那里没有类型成员 ValueType
(所以我们不能使用类型 Test#ValueType
).尝试定义类型 class
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]]