Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 如何解决泛型的隐式问题(使用无形状指南示例)?_Scala_Shapeless - Fatal编程技术网

Scala 如何解决泛型的隐式问题(使用无形状指南示例)?

Scala 如何解决泛型的隐式问题(使用无形状指南示例)?,scala,shapeless,Scala,Shapeless,我正试图按照优秀的《变形指南》学习变形。 但是,在尝试这个例子时,我遇到了几个绊脚石。 其中之一是如何隐式解析Generic[IceCream]。 我还没有为泛型[冰淇淋]的实例声明隐式val,但它是可用的。怎么做 代码看起来像这样,编译得很好 import shapeless._ case class IceCream(name: String, numCherries: Int, inCone: Boolean) case class Employee(name: String, numb

我正试图按照优秀的《变形指南》学习变形。 但是,在尝试这个例子时,我遇到了几个绊脚石。 其中之一是如何隐式解析
Generic[IceCream]
。 我还没有为泛型[冰淇淋]的实例声明
隐式val
,但它是可用的。怎么做

代码看起来像这样,编译得很好

import shapeless._

case class IceCream(name: String, numCherries: Int, inCone: Boolean)
case class Employee(name: String, number: Int, manager: Boolean)

trait CSVEncoder[A] {
  def encode(value: A): List[String]
}
object CSVEncoder {
  // "Summoner" method
  def apply[A](implicit enc: CSVEncoder[A]): CSVEncoder[A] =
    enc
  // "Constructor" method
  def instance[A](func: A => List[String]): CSVEncoder[A] =
    new CSVEncoder[A] {
      def encode(value: A): List[String] =
        func(value)
    }
}
object AdvancedShapelessUsage extends App {
  //Define all typeclass instances here
  def createEncoder[A](func: A => List[String]): CSVEncoder[A] =
    new CSVEncoder[A] {
      def encode(value: A): List[String] = func(value)
    }
  implicit val stringEncoder: CSVEncoder[String] =
    createEncoder(str => List(str))
  implicit val intEncoder: CSVEncoder[Int] =
    createEncoder(num => List(num.toString))
  implicit val booleanEncoder: CSVEncoder[Boolean] =
    createEncoder(bool => List(if (bool) "yes" else "no"))
  implicit val hnilEncoder: CSVEncoder[HNil] =
    createEncoder(hnil => Nil)
  implicit def hlistEncoder[H, T <: HList](implicit hEncoder: CSVEncoder[H], tEncoder: CSVEncoder[T]): CSVEncoder[H :: T] =
    createEncoder {
      case h :: t =>
        hEncoder.encode(h) ++ tEncoder.encode(t)
    }


  implicit def genericEncoder[A, R]( //Use the Aux pattern to take out the `Repr` type 
    implicit gen: Generic[A] {
      type Repr = R
    },
    enc: CSVEncoder[R]): CSVEncoder[A] = createEncoder(a => enc.encode(gen.to(a)))

  val iceCreams: List[IceCream] = List(
    IceCream("Sundae", 1, false),
    IceCream("Cornetto", 0, true),
    IceCream("Banana Split", 0, false))

  def writeCsv[A](values: List[A])(implicit enc: CSVEncoder[A]): String =
    values.map(value => enc.encode(value).mkString(",")).mkString("\n")

  writeCsv(iceCreams)

}
导入无形状_
案例类冰淇淋(名称:String,numCherries:Int,inCone:Boolean)
案例类Employee(名称:String,编号:Int,经理:Boolean)
特征编码器[A]{
def encode(值:A):列表[字符串]
}
目标编码器{
//“召唤者”法
def apply[A](隐式enc:CSVEncoder[A]):CSVEncoder[A]=
enc
//“构造函数”方法
def实例[A](func:A=>List[String]):CSVEncoder[A]=
新CSVEncoder[A]{
def encode(值:A):列表[字符串]=
func(值)
}
}
对象高级ShapeLesSage扩展应用程序{
//在此处定义所有typeclass实例
def createEncoder[A](func:A=>List[String]):CSVEncoder[A]=
新CSVEncoder[A]{
def encode(值:A):列表[字符串]=func(值)
}
隐式val stringEncoder:CSVEncoder[String]=
createEncoder(str=>List(str))
隐式val intEncoder:CSVEncoder[Int]=
createEncoder(num=>List(num.toString))
隐式val booleancoder:CSVEncoder[Boolean]=
createEncoder(bool=>List(如果(bool)“是”或“否”))
隐式val-hnilEncoder:CSVEncoder[HNil]=
createEncoder(hnil=>Nil)
隐式def hlistEncoder[H,T
hEncoder.encode(h)++tEncoder.encode(t)
}
隐式def genericEncoder[A,R](//使用Aux模式取出'Repr'类型
隐式生成:泛型[A]{
类型Repr=R
},
enc:CSVEncoder[R]):CSVEncoder[A]=createEncoder(A=>enc.encode(gen.to(A)))
val冰淇淋:列表[冰淇淋]=列表(
冰淇淋(“圣代”,1,假的),
冰淇淋(“Cornetto”,0,真的),
冰淇淋(“香蕉片”,0,假))
def writeCsv[A](值:列表[A])(隐式enc:CSVEncoder[A]):字符串=
values.map(value=>enc.encode(value).mkString(“,”).mkString(“\n”)
writeCsv(冰淇淋)
}
当我们说
隐式gen:Generic[A]{
类型Repr=R
}

我认为编译器将查找泛型[IceCream],然后引用
Repr
并将其分配给R类型。
我不明白如果没有通用的[冰淇淋]是如何解决的。所以我想我不明白。如果我正确理解了你的问题,你想知道通用的[冰淇淋]是如何解决的。解决这个问题有两个原因:

  • 任何特征T的隐式范围包括其伴生对象T
  • Shapeless有一个宏,它生成一个通用的[T]:这个用例是名为“隐式物化器”的宏的常见用法

  • 所以,每当我有一个case类并导入shapeless时,我都会隐式地提供case类类型的Generic[]吗?你甚至不需要在你的类中导入shapeless。这是由于Scala隐式解析机制:你需要隐式Generic[C]Scala会在Generic的伴生对象中查找它,但Generic是一个不成形的typeclass,对吗?如果没有不成形的导入,这是行不通的。这不准确:不成形在类路径中,因为您将其添加为项目的依赖项。但是,在源代码中,您没有直接使用Generic,因此不需要导入啊,这就是我需要的指导。谢谢。