Scala 使用隐式查找;“一”;要注入的HList typeclass的元素

Scala 使用隐式查找;“一”;要注入的HList typeclass的元素,scala,shapeless,Scala,Shapeless,代码如下: 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

代码如下:

    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)

trait服务[T我真的不知道你为什么需要这个:)

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

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()
}
有可能使它更通用(因此它将检查您需要的类型是否在
HList
,如果不在,则进行三次检查)(使用Curry Howard同构,由Miles Sabin撰写的解释性文章:):

一切正常

operate(new C) //> handling c
operate(new A) //> handling a b
operate(new B) //> handling a b
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()
}
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)