委托给更具体的上下文绑定(附加隐式参数)
Delegate to a more specific Context Bound (additional implicit parameter)
我正在尝试创建一个 ZIO 模块示例,它有两个实现:
- 将 YAML 与 circe-yaml 结合使用
- 将 HOCON 与 pureConfig 结合使用
我的一般界面是这样的:
trait Service[R] {
def load[T <: Component](ref: CompRef): RIO[R, T]
}
现在我的 YAML 实现如下所示:
def loadYaml[T <: Component: Decoder](ref: CompRef): RIO[Any, T] = {...}
Decoder
是特定于实现的。
现在的问题是如何将服务实现委托给 loadYaml
。
我尝试了以下方法:
val components: Components.Service[Any] = new Components.Service[Any] {
implicit val decodeComponent: Decoder[Component] =
List[Decoder[Component]](
Decoder[DbConnection].widen,
...
).reduceLeft(_ or _)
def load[T <: Component](ref: CompRef): RIO[Any, T] = loadYaml[T] (ref)
}
这给了我:
Error:(62, 20) could not find implicit value for evidence parameter of type io.circe.Decoder[T]
loadYaml[T] (ref)
有办法实现吗?
我在 Github 上创建了一个示例项目:zio-comps-module
这里描述了这个想法:Decouple the Program from its Implementation with ZIO modules
好的,我找到了解决办法。我所要做的就是调整 load
函数:
def load[T <: Component](ref: CompRef): RIO[ComponentsEnv, T] = {
loadConf[Component](ref).map { case c: T => c }
}
类型为 Component
的第一个 loadConf
。
第二次投射结果(Component
) 结果类型T
.
这有效,但给你丑陋的警告:
[warn] /Users/mpa/dev/Github/pme123/zio-comps-module/hocon/src/pme123/zio/comps/hocon/HoconComps.scala:37:46: abstract type pattern T is unchecked since it is eliminated by erasure
[warn] loadConf[Component](ref).map { case c: T => c }
[warn] ^
[warn] /Users/mpa/dev/Github/pme123/zio-comps-module/hocon/src/pme123/zio/comps/hocon/HoconComps.scala:37:36: match may not be exhaustive.
[warn] It would fail on the following inputs: DbConnection(_, _, _, _), DbLookup(_, _, _, _), MessageBundle(_, _)
[warn] loadConf[Component](ref).map { case c: T => c }
[warn] ^
[warn] two warnings found
更新 - 我找到了一个消除警告的解决方案:
第十次阅读警告 unchecked since it is eliminated by erasure
后,我记得可以通过添加 ClassTag
as Context Bound.[=20 来解决这个问题=]
服务现在看起来
trait Service[R] {
def load[T <: Component: ClassTag](ref: CompRef): RIO[R, T]
}
如果问题在于你的特质
def load[T <: Component]
在实现中你需要
def loadYaml[T <: Component: Decoder]
那么也许你只需要参数化 Decoder
trait Service[R, D] {
def load[T <: Component: D](ref: CompRef): RIO[R, T]
}
如果D
的不同类型之间没有关系,那么你可以将其定义为Any
,然后将特征设为trait Service[R, +D]
。
我正在尝试创建一个 ZIO 模块示例,它有两个实现:
- 将 YAML 与 circe-yaml 结合使用
- 将 HOCON 与 pureConfig 结合使用
我的一般界面是这样的:
trait Service[R] {
def load[T <: Component](ref: CompRef): RIO[R, T]
}
现在我的 YAML 实现如下所示:
def loadYaml[T <: Component: Decoder](ref: CompRef): RIO[Any, T] = {...}
Decoder
是特定于实现的。
现在的问题是如何将服务实现委托给 loadYaml
。
我尝试了以下方法:
val components: Components.Service[Any] = new Components.Service[Any] {
implicit val decodeComponent: Decoder[Component] =
List[Decoder[Component]](
Decoder[DbConnection].widen,
...
).reduceLeft(_ or _)
def load[T <: Component](ref: CompRef): RIO[Any, T] = loadYaml[T] (ref)
}
这给了我:
Error:(62, 20) could not find implicit value for evidence parameter of type io.circe.Decoder[T]
loadYaml[T] (ref)
有办法实现吗?
我在 Github 上创建了一个示例项目:zio-comps-module
这里描述了这个想法:Decouple the Program from its Implementation with ZIO modules
好的,我找到了解决办法。我所要做的就是调整 load
函数:
def load[T <: Component](ref: CompRef): RIO[ComponentsEnv, T] = {
loadConf[Component](ref).map { case c: T => c }
}
类型为 Component
的第一个 loadConf
。
第二次投射结果(Component
) 结果类型T
.
这有效,但给你丑陋的警告:
[warn] /Users/mpa/dev/Github/pme123/zio-comps-module/hocon/src/pme123/zio/comps/hocon/HoconComps.scala:37:46: abstract type pattern T is unchecked since it is eliminated by erasure
[warn] loadConf[Component](ref).map { case c: T => c }
[warn] ^
[warn] /Users/mpa/dev/Github/pme123/zio-comps-module/hocon/src/pme123/zio/comps/hocon/HoconComps.scala:37:36: match may not be exhaustive.
[warn] It would fail on the following inputs: DbConnection(_, _, _, _), DbLookup(_, _, _, _), MessageBundle(_, _)
[warn] loadConf[Component](ref).map { case c: T => c }
[warn] ^
[warn] two warnings found
更新 - 我找到了一个消除警告的解决方案:
第十次阅读警告 unchecked since it is eliminated by erasure
后,我记得可以通过添加 ClassTag
as Context Bound.[=20 来解决这个问题=]
服务现在看起来
trait Service[R] {
def load[T <: Component: ClassTag](ref: CompRef): RIO[R, T]
}
如果问题在于你的特质
def load[T <: Component]
在实现中你需要
def loadYaml[T <: Component: Decoder]
那么也许你只需要参数化 Decoder
trait Service[R, D] {
def load[T <: Component: D](ref: CompRef): RIO[R, T]
}
如果D
的不同类型之间没有关系,那么你可以将其定义为Any
,然后将特征设为trait Service[R, +D]
。