为 Object 的上下文边界提供隐式证据
Providing implicit evidence for context bounds on Object
我试图在一些 Spark Scala 代码中编写一些抽象,但是 运行 在使用对象时遇到了一些问题。我正在使用 Spark 的 Encoder
,它用于将大小写 classes 转换为数据库模式,但我认为这个问题适用于任何 context bound.
这是我正在尝试执行的操作的最小代码示例:
package com.sample.myexample
import org.apache.spark.sql.Encoder
import scala.reflect.runtime.universe.TypeTag
case class MySparkSchema(id: String, value: Double)
abstract class MyTrait[T: TypeTag: Encoder]
object MyObject extends MyTrait[MySparkSchema]
由于以下编译错误而失败:
Unable to find encoder for type com.sample.myexample.MySparkSchema. An implicit Encoder[com.sample.myexample.MySparkSchema] is needed to store com.sample.myexample.MySparkSchema instances in a Dataset. Primitive types (Int, String, etc) and Product types (case classes) are supported by importing spark.implicits._ Support for serializing other types will be added in future releases.
我试过这样定义对象中的隐式证据:(IntelliJ 建议使用 import 语句,但看起来有点奇怪)
import com.sample.myexample.MyObject.encoder
object MyObject extends MyTrait[MySparkSchema] {
implicit val encoder: Encoder[MySparkSchema] = Encoders.product[MySparkSchema]
}
失败并显示错误消息
MyTrait.scala:13:25: super constructor cannot be passed a self reference unless parameter is declared by-name
我尝试的另一件事是将对象转换为 class 并向构造函数提供隐式证据:
class MyObject(implicit evidence: Encoder[MySparkSchema]) extends MyTrait[MySparkSchema]
这可以编译并工作正常,但代价是 MyObject
现在变成了 class
。
问题:是否可以在扩展特征时为上下文边界提供隐式证据?还是隐含的证据迫使我创建构造函数并改用 class
?
您的第一个错误几乎就是解决方案,您必须导入 spark.implicits._
产品类型。
你可以这样做:
val spark: SparkSession = SparkSession.builder().getOrCreate()
import spark.implicits._
完整示例
package com.sample.myexample
import org.apache.spark.sql.Encoder
import scala.reflect.runtime.universe.TypeTag
case class MySparkSchema(id: String, value: Double)
abstract class MyTrait[T: TypeTag: Encoder]
val spark: SparkSession = SparkSession.builder().getOrCreate()
import spark.implicits._
object MyObject extends MyTrait[MySparkSchema]
我试图在一些 Spark Scala 代码中编写一些抽象,但是 运行 在使用对象时遇到了一些问题。我正在使用 Spark 的 Encoder
,它用于将大小写 classes 转换为数据库模式,但我认为这个问题适用于任何 context bound.
这是我正在尝试执行的操作的最小代码示例:
package com.sample.myexample
import org.apache.spark.sql.Encoder
import scala.reflect.runtime.universe.TypeTag
case class MySparkSchema(id: String, value: Double)
abstract class MyTrait[T: TypeTag: Encoder]
object MyObject extends MyTrait[MySparkSchema]
由于以下编译错误而失败:
Unable to find encoder for type com.sample.myexample.MySparkSchema. An implicit Encoder[com.sample.myexample.MySparkSchema] is needed to store com.sample.myexample.MySparkSchema instances in a Dataset. Primitive types (Int, String, etc) and Product types (case classes) are supported by importing spark.implicits._ Support for serializing other types will be added in future releases.
我试过这样定义对象中的隐式证据:(IntelliJ 建议使用 import 语句,但看起来有点奇怪)
import com.sample.myexample.MyObject.encoder
object MyObject extends MyTrait[MySparkSchema] {
implicit val encoder: Encoder[MySparkSchema] = Encoders.product[MySparkSchema]
}
失败并显示错误消息
MyTrait.scala:13:25: super constructor cannot be passed a self reference unless parameter is declared by-name
我尝试的另一件事是将对象转换为 class 并向构造函数提供隐式证据:
class MyObject(implicit evidence: Encoder[MySparkSchema]) extends MyTrait[MySparkSchema]
这可以编译并工作正常,但代价是 MyObject
现在变成了 class
。
问题:是否可以在扩展特征时为上下文边界提供隐式证据?还是隐含的证据迫使我创建构造函数并改用 class
?
您的第一个错误几乎就是解决方案,您必须导入 spark.implicits._
产品类型。
你可以这样做:
val spark: SparkSession = SparkSession.builder().getOrCreate()
import spark.implicits._
完整示例
package com.sample.myexample
import org.apache.spark.sql.Encoder
import scala.reflect.runtime.universe.TypeTag
case class MySparkSchema(id: String, value: Double)
abstract class MyTrait[T: TypeTag: Encoder]
val spark: SparkSession = SparkSession.builder().getOrCreate()
import spark.implicits._
object MyObject extends MyTrait[MySparkSchema]