handling a b operate(new B) //> handling a b-6ren">
gpt4 book ai didi

scala - 使用隐式查找List类型类的 "One"元素注入(inject)

转载 作者:行者123 更新时间:2023-12-01 23:55:15 25 4
gpt4 key购买 nike

代码如下:

    trait Service[T<: HList] {
def doStuff(): Unit
}

class A
class B
class C

class ServiceAB extends Service[A :: B :: HNil] {
override def doStuff(): Unit = println("handling a b")
}

class ServiceC extends Service[C :: HNil] {
override def doStuff(): Unit = println("handling c")
}

implicit val serviceAB = new ServiceAB
implicit val serviceC = new ServiceC

def operate[T, W <: HList](x: T)(implicit service: Service[W]) = {
service.doStuff()
}

operate(new C)

我只是想知道在执行 operate(new C) 时是否有可能或者我应该在类型级别编写什么代码来注入(inject)隐式 serviceC,因为类 C 是 ServiceC 类型类的 HList 的元素?

提前致谢

最佳答案

我真的不知道你为什么需要这个:)

所以你的代码可以工作,但是如果你显式传递类型参数:

operate[C, C :: HNil](new C)

如果你想要相同但隐含地,你可以定义你的类类型:

trait Service[L <: HList, U] { def doStuff(): Unit }

trait lowPriority {
implicit def otherwise[L <: HList, U] =
new Service[L, U] {
def doStuff(): Unit = println("handling otherwise")
}
}

object Service extends lowPriority {
implicit def ab[L <: HList, U]
(implicit e: L =:= (A :: B :: HNil),
s: Selector[L, U]) =
new Service[L, U] {
def doStuff(): Unit = println("handling a b")
}

implicit def c[L <: HList, U]
(implicit e: L =:= (C :: HNil),
s: Selector[L, U]) =
new Service[L, U] {
def doStuff(): Unit = println("handling c")
}
}
}

def operate[T, W <: HList](x: T)(implicit service: Service[W, T]) = {
service.doStuff()
}

所以这按预期工作:

operate(new C) //> handling c
operate(new A) //> handling a b
operate(new B) //> handling a b

可以使它更通用(所以它会检查你需要的类型是否在 HList 中,如果不在则不然)(使用 Curry-Howard 同构,很棒的文章和解释迈尔斯·萨宾 (Miles Sabin):http://www.chuusai.com/2011/06/09/scala-union-types-curry-howard/ ):

import reflect.runtime.universe._

type ¬[A] = A => Nothing
type ∨[T, U] = ¬[¬[T] with ¬[U]]
type ¬¬[A] = ¬[¬[A]]

class A
class B
class C
class D //> additional class for example

trait Service[L <: HList, U] { def doStuff(): Unit }

trait lowPriority {
implicit def otherwise[L <: HList, U] =
new Service[L, U] {
def doStuff(): Unit = println("handling otherwise")
}
}

object Service extends lowPriority {
implicit def ab[L <: HList, U]
(implicit e: (¬¬[U] <:< (A ∨ B)),
s: Selector[L, TypeTag[U]]) =
new Service[L, U] {
def doStuff(): Unit = println("handling a b")
}

implicit def c[L <: HList, U](implicit e: U =:= C, s: Selector[L, TypeTag[U]]) =
new Service[L, U] {
def doStuff(): Unit = println("handling c")
}
}
}

def operateBi[T, W <: HList](x: T, w: W)(implicit service: Service[W, T]) = {
service.doStuff()
}

定义 HList 类型:

val hl1 = implicitly[TypeTag[A]] :: implicitly[TypeTag[B]] :: HNil
val hl2 = implicitly[TypeTag[C]] :: HNil

operateBi(new C, hl1)
operateBi(new A, hl2)
operateBi(new B, hl1)
operateBi(new D, hl1)

按预期工作。

关于scala - 使用隐式查找List类型类的 "One"元素注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24052732/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com