解析隐式然后使用存储在其中的类型来解析第二个隐式
resolve an implicit then use the type stored in it to resolve a second implicit
我正在尝试解析隐式,然后使用存储在其中的类型来解析第二个隐式。
这是代码:
sealed trait ReturnTypeRetriever[T] {
type ReturnType
}
object ReturnTypeRetrievers {
implicit val expl = new ReturnTypeRetriever[ExplorationStreamFilter] {
type ReturnType = SimpleFilter[Context, Context]
}
}
sealed trait Retriever[T, +R] {
def get(config: Config): R //SimpleFilter[Context, Context]
}
object Retrievers {
// implementation here for T=ExplorationStreamFilter and R=SimpleFilter[Context, Context]
implicit val expl = new Retriever[ExplorationStreamFilter, SimpleFilter[Context, Context]] {
override def get(config: Config) = {..}
}
// putting it all together
def getOrEmpty[A](config: Config)(implicit evret: ReturnTypeRetriever[A]) = {
val ev = implicitly[Retriever[A, evret.ReturnType]] <-- ERROR 1: cannot find implicit defined above ^
ev.get(config)
}
}
这样称呼它:
lazy val exploration = getOrEmpty[ExplorationStreamFilter](config) <--- ERROR 2: cannot find implicit here either
编译显示 2 个错误:
ERROR 1 message: could not find implicit value for parameter e: Retriever[A,evret.ReturnType]
[error] val ev = implicitly[Retriever[A, evret.ReturnType]]
ERROR 2 message: could not find implicit value for parameter evret: ReturnTypeRetriever[ExplorationStreamFilter]
[error] lazy val exploration = getOrEmpty[ExplorationStreamFilter](config)
为什么编译器找不到隐含的?有什么解决方案?
这似乎有效。
它使用 Aux 模式和 Partially-applied 技巧。
sealed trait ReturnTypeRetriever[T] {
type ReturnType
}
// It should be named equally to the trait, in order to be a companion.
// That way, implicits will be in scope.
object ReturnTypeRetriever {
// Aux pattern!
// Used to transform a type member, into a type parameter, for better inference.
type Aux[T, R] = ReturnTypeRetriever[T] { type ReturnType = R }
// Implicits must always have explicit type signatures.
implicit final val expl: Aux[ExplorationStreamFilter, SimpleFilter[Context, Context]] =
new ReturnTypeRetriever[ExplorationStreamFilter] {
override final type ReturnType = SimpleFilter[Context, Context]
}
}
sealed trait Retriever[T, +R] {
def get(config: Config): R
}
object Retriever {
implicit final val expl: Retriever[ExplorationStreamFilter, SimpleFilter[Context, Context]] =
new Retriever[ExplorationStreamFilter, SimpleFilter[Context, Context]] {
override final def get(config: Config): SimpleFilter[Context, Context] =
???
}
// Ideally, you should make this class private[package]
// Where package is the package in which this is defined.
final class GetOrEmptyPartiallyApplied[A](private val dummy: Boolean) extends AnyVal {
def apply[R](config: Config)
(implicit rtr: ReturnTypeRetriever.Aux[A, R], retriever: Retriever[A, R]): R =
retriever.get(config)
}
// Partially-applied trick!
// Used to allow partial application of a type.
// User only needs to specify A, the compiler will infer R.
def getOrEmpty[A]: GetOrEmptyPartiallyApplied[A] =
new GetOrEmptyPartiallyApplied(dummy = true)
}
(我不明白 ReturnTypeRetriever
trait 的目的是什么。但我保留它以保留原始问题)
我正在尝试解析隐式,然后使用存储在其中的类型来解析第二个隐式。
这是代码:
sealed trait ReturnTypeRetriever[T] {
type ReturnType
}
object ReturnTypeRetrievers {
implicit val expl = new ReturnTypeRetriever[ExplorationStreamFilter] {
type ReturnType = SimpleFilter[Context, Context]
}
}
sealed trait Retriever[T, +R] {
def get(config: Config): R //SimpleFilter[Context, Context]
}
object Retrievers {
// implementation here for T=ExplorationStreamFilter and R=SimpleFilter[Context, Context]
implicit val expl = new Retriever[ExplorationStreamFilter, SimpleFilter[Context, Context]] {
override def get(config: Config) = {..}
}
// putting it all together
def getOrEmpty[A](config: Config)(implicit evret: ReturnTypeRetriever[A]) = {
val ev = implicitly[Retriever[A, evret.ReturnType]] <-- ERROR 1: cannot find implicit defined above ^
ev.get(config)
}
}
这样称呼它:
lazy val exploration = getOrEmpty[ExplorationStreamFilter](config) <--- ERROR 2: cannot find implicit here either
编译显示 2 个错误:
ERROR 1 message: could not find implicit value for parameter e: Retriever[A,evret.ReturnType]
[error] val ev = implicitly[Retriever[A, evret.ReturnType]]
ERROR 2 message: could not find implicit value for parameter evret: ReturnTypeRetriever[ExplorationStreamFilter]
[error] lazy val exploration = getOrEmpty[ExplorationStreamFilter](config)
为什么编译器找不到隐含的?有什么解决方案?
这似乎有效。
它使用 Aux 模式和 Partially-applied 技巧。
sealed trait ReturnTypeRetriever[T] {
type ReturnType
}
// It should be named equally to the trait, in order to be a companion.
// That way, implicits will be in scope.
object ReturnTypeRetriever {
// Aux pattern!
// Used to transform a type member, into a type parameter, for better inference.
type Aux[T, R] = ReturnTypeRetriever[T] { type ReturnType = R }
// Implicits must always have explicit type signatures.
implicit final val expl: Aux[ExplorationStreamFilter, SimpleFilter[Context, Context]] =
new ReturnTypeRetriever[ExplorationStreamFilter] {
override final type ReturnType = SimpleFilter[Context, Context]
}
}
sealed trait Retriever[T, +R] {
def get(config: Config): R
}
object Retriever {
implicit final val expl: Retriever[ExplorationStreamFilter, SimpleFilter[Context, Context]] =
new Retriever[ExplorationStreamFilter, SimpleFilter[Context, Context]] {
override final def get(config: Config): SimpleFilter[Context, Context] =
???
}
// Ideally, you should make this class private[package]
// Where package is the package in which this is defined.
final class GetOrEmptyPartiallyApplied[A](private val dummy: Boolean) extends AnyVal {
def apply[R](config: Config)
(implicit rtr: ReturnTypeRetriever.Aux[A, R], retriever: Retriever[A, R]): R =
retriever.get(config)
}
// Partially-applied trick!
// Used to allow partial application of a type.
// User only needs to specify A, the compiler will infer R.
def getOrEmpty[A]: GetOrEmptyPartiallyApplied[A] =
new GetOrEmptyPartiallyApplied(dummy = true)
}
(我不明白 ReturnTypeRetriever
trait 的目的是什么。但我保留它以保留原始问题)