这个想法来自这个视频:https://www.youtube.com/watch?v=bfabet0pre0&t=526s,他们讨论了如何通过实现自定义类型来实现类型安全。
一个可能的琐碎实现是
trait Col[Self] { self: Self =>
}
trait Id extends Col[Id]
object IdCol extends Id
trait Val extends Col[Val]
object ValCol extends Val
trait Comment extends Col[Comment]
object CommentCol extends Comment
case class DataSet[Schema >: Nothing](df: DataFrame) {
def validate[T1 <: Col[T1], T2 <: Col[T2]](
col1: (Col[T1], String),
col2: (Col[T2], String)
): Option[DataSet[Schema with T1 with T2]] =
if (df.columns
.map(e => e.toLowerCase)
.filter(
e =>
e.toLowerCase() == col1._2.toLowerCase || e
.toLowerCase() == col2._2.toLowerCase
)
.length >= 1)
Some(DataSet[Schema with T1 with T2](df))
else None
}
object SchemaTypes extends App {
lazy val spark: SparkSession = SparkSession
.builder()
.config(
new SparkConf()
.setAppName(
getClass()
.getName()
)
)
.getOrCreate()
import spark.implicits._
val df = Seq(
(1, "a", "first value"),
(2, "b", "second value"),
(3, "c", "third value")
).toDF("Id", "Val", "Comment")
val myData =
DataSet/*[Id with Val with Comment]*/(df)
.validate(IdCol -> "Id", ValCol -> "Val")
myData match {
case None => throw new java.lang.Exception("Required columns missing")
case _ =>
}
}
mydata的类型为 Option[DataSet[Nothing with T1 with T2]]
. 这是有意义的,因为构造函数被称为w/o任何类型参数,但在视频中,它们显示的类型与 DataSet[T1 with T2]
.
当然,通过传递显式类型来更改调用需要 Nothing
out,但指定类型参数值是多余的,因为类型已经包含在arg列表中。
val myData =
DataSet[Id with Val with Comment](df).validate(IdCol -> "Id", ValCol -> "Val")
2条答案
按热度按时间lp0sw83n1#
类型
Id
以及Val
因为有IdCol
以及ValCol
内部.validate
. 但是类型Comment
无法推断。所以试试看https://scastie.scala-lang.org/yj0hnpkyqfcrekq8zv4d7a
实际上如果你指定
DataSet[Id with Val with Comment](df)
类型将为Option[DataSet[Id with Val with Comment with Id with Val]]
,等于(=:=
)至Option[DataSet[Id with Val with Comment]]
.好吧,我一直看录像直到那个时候。我猜演讲者试图解释他们的想法(结合f-有界多态性)
T <: Col[T]
具有交叉点类型T with U
)你不应该照字面理解他们的幻灯片,可能会有不准确的地方。首先他们放映幻灯片
这个代码可以用
然后放映幻灯片
但是这个演示代码与上一张幻灯片不符。你应该定义
所以把它当作一个想法,而不是字面意思。
你可以有类似的东西
o8x7eapl2#
dmytro mitin的回答很好,但我想提供更多的信息。
如果你写的是
DataSet(df).validate(...)
,的类型参数DataSet(df)
首先推断。给你Nothing
因为没有任何信息可以让它成为其他东西。所以Schema
是Nothing
,和Schema with T1 with T2
(出现在validate
)是Nothing with Id with Val
.