【发布时间】:2019-01-05 10:32:53
【问题描述】:
我有一个 Any 数组(在现实生活中,它是一个 Spark Row,但足以隔离问题)
object Row {
val buffer : Array[Any] = Array(42, 21, true)
}
我想对其元素应用一些操作。
所以,我定义了一个简单的 ADT 来定义一个 compute 对类型 A 的操作
trait Op[A] {
def cast(a: Any) : A = a.asInstanceOf[A]
def compute(a: A) : A
}
case object Count extends Op[Int] {
override def compute(a: Int): Int = a + 1
}
case object Exist extends Op[Boolean] {
override def compute(a: Boolean): Boolean = a
}
鉴于我有一个所有操作的列表,并且我知道要对每个元素应用哪个操作,让我们使用这些操作。
object GenericsOp {
import Row._
val ops = Seq(Count, Exist)
def compute() = {
buffer(0) = ops(0).compute(ops(0).cast(buffer(0)))
buffer(1) = ops(0).compute(ops(0).cast(buffer(1)))
buffer(2) = ops(1).compute(ops(1).cast(buffer(2)))
}
}
根据设计,对于给定的操作,类型在 cast 和 combine 之间对齐。但不幸的是,以下代码无法编译。错误是
Type mismatch, expected: _$1, actual: AnyVal
有没有办法让它工作?
我找到了一种解决方法,即使用抽象类型成员而不是类型参数。
object AbstractOp extends App {
import Row._
trait Op {
type A
def compute(a: A) : A
}
case object Count extends Op {
type A = Int
override def compute(a: Int): Int = a + 1
}
case object Exist extends Op {
type A = Boolean
override def compute(a: Boolean): Boolean = a
}
val ops = Seq(Count, Exist)
def compute() = {
val op0 = ops(0)
val op1 = ops(1)
buffer(0) = ops(0).compute(buffer(0).asInstanceOf[op0.A])
buffer(1) = ops(0).compute(buffer(1).asInstanceOf[op0.A])
buffer(2) = ops(1).compute(buffer(2).asInstanceOf[op1.A])
}
}
有没有更好的办法?
【问题讨论】:
-
我不确定你在那里尝试实现什么,但你知道 Shapeless'
HLists? -
嗨@AndreyTyukin。我已经改写了这个问题,以使我想要实现的目标更加清晰。我知道 Shapeless,但我想了解原始 Scala 的可能性。
标签: scala