Scala 在Shapeless中,TypeClass trait的emptyCoproduct和coproduct方法的目的是什么

Scala 在Shapeless中,TypeClass trait的emptyCoproduct和coproduct方法的目的是什么,scala,typeclass,shapeless,type-level-computation,Scala,Typeclass,Shapeless,Type Level Computation,我还不完全清楚emptyCoProduct和coproduct的TypeClass特性在Shapeless中的作用是什么 什么时候会使用TypeClass特性而不是ProductTypeClass 这两种方法的实现方式有哪些示例?假设我有一个简单的类型类: trait Weight[A] { def apply(a: A): Int } object Weight { def apply[A](f: A => Int) = new Weight[A] { def apply(a: A

我还不完全清楚
emptyCoProduct
coproduct
TypeClass
特性在Shapeless中的作用是什么

什么时候会使用
TypeClass
特性而不是
ProductTypeClass


这两种方法的实现方式有哪些示例?

假设我有一个简单的类型类:

trait Weight[A] { def apply(a: A): Int }

object Weight {
  def apply[A](f: A => Int) = new Weight[A] { def apply(a: A) = f(a) }
}
import shapeless._

implicit object WeightTypeClass extends ProductTypeClass[Weight] {
  def emptyProduct: Weight[HNil] = Weight(_ => 0)
  def product[H, T <: HList](hw: Weight[H], tw: Weight[T]): Weight[H :: T] =
    Weight { case (h :: t) => hw(h) + tw(t) }
  def project[F, G](w: => Weight[G], to: F => G, from: G => F): Weight[F] =
    Weight(f => w(to(f)))
}
还有一些例子:

implicit val stringWeight: Weight[String] = Weight(_.size)
implicit def intWeight: Weight[Int] = Weight(identity)
和一个案例类:

case class Foo(i: Int, s: String)
和ADT:

sealed trait Root
case class Bar(i: Int) extends Root
case class Baz(s: String) extends Root
我可以为我的类型类定义
ProductTypeClass
实例:

trait Weight[A] { def apply(a: A): Int }

object Weight {
  def apply[A](f: A => Int) = new Weight[A] { def apply(a: A) = f(a) }
}
import shapeless._

implicit object WeightTypeClass extends ProductTypeClass[Weight] {
  def emptyProduct: Weight[HNil] = Weight(_ => 0)
  def product[H, T <: HList](hw: Weight[H], tw: Weight[T]): Weight[H :: T] =
    Weight { case (h :: t) => hw(h) + tw(t) }
  def project[F, G](w: => Weight[G], to: F => G, from: G => F): Weight[F] =
    Weight(f => w(to(f)))
}
但是

然后:

scala> object WeightHelper extends TypeClassCompanion[Weight]
defined object WeightHelper

scala> import WeightHelper.auto._
import WeightHelper.auto._

scala> implicitly[Weight[Root]]
res0: Weight[Root] = Weight$$anon$1@7bc44e19
上面所有的其他东西仍然有效


总而言之:Shapeless的
CopProduct
是对ADT的一种抽象,一般来说,您应该为您的类型类提供
TypeClass
实例,而不是尽可能只提供
ProductTypeClass

从Shapeless 2.3.2开始,上面的示例似乎没有编译。以下是更新后的版本供将来参考:

import shapeless._
import shapeless.test._

trait Weight[A] { def apply(a: A): Int }

object Weight {
  def apply[A](f: A => Int) = new Weight[A] { def apply(a: A) = f(a) }
}

case class Foo(i: Int, s: String)

sealed trait Root
case class Bar(i: Int) extends Root
case class Baz(s: String) extends Root

object Base {
  implicit val stringWeight: Weight[String] = Weight(_.size)
  implicit def intWeight: Weight[Int] = Weight(identity)
}

object ProductTC {
  object WeightHelper extends ProductTypeClassCompanion[Weight] {
    object typeClass extends ProductTypeClass[Weight] {
      def emptyProduct: Weight[HNil] = Weight(_ => 0)
      def product[H, T <: HList](hw: Weight[H], tw: Weight[T]): Weight[H :: T] =
        Weight { case (h :: t) => hw(h) + tw(t) }
      def project[F, G](w: => Weight[G], to: F => G,from: G => F): Weight[F] =
        Weight(f => w(to(f)))
    }
  }

  import Base._
  import WeightHelper._

  implicitly[Weight[Foo]]
  implicitly[Weight[Bar]]
  implicitly[Weight[Baz]]

  illTyped("implicitly[Weight[Root]]")
}

object TC {
  object WeightTypeClass extends TypeClassCompanion[Weight] {
    object typeClass extends TypeClass[Weight] {
      def emptyProduct: Weight[HNil] = Weight(_ => 0)
      def product[H, T <: HList](hw: Weight[H], tw: Weight[T]): Weight[H :: T] =
        Weight { case (h :: t) => hw(h) + tw(t) }
      def project[F, G](w: => Weight[G], to: F => G, from: G => F): Weight[F] =
        Weight(f => w(to(f)))
      def emptyCoproduct: Weight[CNil] = Weight(_ => 0)
      def coproduct[L, R <: Coproduct]
        (lw: => Weight[L], rw: => Weight[R]): Weight[L :+: R] = Weight {
        case Inl(h) => lw(h)
        case Inr(t) => rw(t)
      }
    }
  }

  import Base._
  import WeightTypeClass._

  implicitly[Weight[Root]]
}
导入无形状_
导入shapeless.test_
特征权重[A]{def apply(A:A):Int}
物体重量{
def apply[A](f:A=>Int)=新权重[A]{def apply(A:A)=f(A)}
}
案例类Foo(i:Int,s:String)
密封性状根
case类条(i:Int)扩展根
case类Baz(s:String)扩展了根
对象库{
隐式val stringWeight:Weight[String]=权重(uu.size)
隐式def intWeight:Weight[Int]=权重(标识)
}
对象产品{
对象WeightHelper扩展ProductTypeClassCompanion[权重]{
对象类型类扩展ProductTypeClass[权重]{
def emptyProduct:重量[HNil]=重量(=>0)
def产品[H,T hw(H)+tw(T)}
def项目[F,G](w:=>Weight[G],to:F=>G,from:G=>F):Weight[F]=
重量(f=>w(至(f)))
}
}
进口基地_
导入权重助手_
隐式[权重[Foo]]
隐式[重量[Bar]]
隐式[权重[Baz]]
类型错误(“隐式[权重[根]]”)
}
对象TC{
对象WeightTypeClass扩展了TypeClassCompanion[权重]{
对象类型类扩展类型类[权重]{
def emptyProduct:重量[HNil]=重量(=>0)
def产品[H,T hw(H)+tw(T)}
def项目[F,G](w:=>Weight[G],to:F=>G,from:G=>F):Weight[F]=
重量(f=>w(至(f)))
def emptyCoproduct:Weight[CNil]=重量(=>0)
def副产品[L,R重量[L],rw:=>重量[R]:重量[L:+:R]=重量{
案例Inl(h)=>lw(h)
案例Inr(t)=>rw(t)
}
}
}
进口基地_
导入WeightTypeClass_
隐式[权重[根]]
}
import shapeless._
import shapeless.test._

trait Weight[A] { def apply(a: A): Int }

object Weight {
  def apply[A](f: A => Int) = new Weight[A] { def apply(a: A) = f(a) }
}

case class Foo(i: Int, s: String)

sealed trait Root
case class Bar(i: Int) extends Root
case class Baz(s: String) extends Root

object Base {
  implicit val stringWeight: Weight[String] = Weight(_.size)
  implicit def intWeight: Weight[Int] = Weight(identity)
}

object ProductTC {
  object WeightHelper extends ProductTypeClassCompanion[Weight] {
    object typeClass extends ProductTypeClass[Weight] {
      def emptyProduct: Weight[HNil] = Weight(_ => 0)
      def product[H, T <: HList](hw: Weight[H], tw: Weight[T]): Weight[H :: T] =
        Weight { case (h :: t) => hw(h) + tw(t) }
      def project[F, G](w: => Weight[G], to: F => G,from: G => F): Weight[F] =
        Weight(f => w(to(f)))
    }
  }

  import Base._
  import WeightHelper._

  implicitly[Weight[Foo]]
  implicitly[Weight[Bar]]
  implicitly[Weight[Baz]]

  illTyped("implicitly[Weight[Root]]")
}

object TC {
  object WeightTypeClass extends TypeClassCompanion[Weight] {
    object typeClass extends TypeClass[Weight] {
      def emptyProduct: Weight[HNil] = Weight(_ => 0)
      def product[H, T <: HList](hw: Weight[H], tw: Weight[T]): Weight[H :: T] =
        Weight { case (h :: t) => hw(h) + tw(t) }
      def project[F, G](w: => Weight[G], to: F => G, from: G => F): Weight[F] =
        Weight(f => w(to(f)))
      def emptyCoproduct: Weight[CNil] = Weight(_ => 0)
      def coproduct[L, R <: Coproduct]
        (lw: => Weight[L], rw: => Weight[R]): Weight[L :+: R] = Weight {
        case Inl(h) => lw(h)
        case Inr(t) => rw(t)
      }
    }
  }

  import Base._
  import WeightTypeClass._

  implicitly[Weight[Root]]
}