我有一个与此问题非常相似的问题:Scala higher kinded type variance
但是,这稍有不同,它不会编译(scala 2.11.8)。
基本思想是采用提供的“事物”数组。如果数组为空,则返回某种类型的默认值(例如Boolean
,Option
,List[Int]
),否则对数组进行操作并产生结果。结果和默认值具有相同的类型。
我面临的挑战是使其能够在广泛的结果类型中使用。
这是一个人为的例子:
trait NullGuard[F[_]] {
def nullGuard[A, B](arr: Array[A], default: F[B])(expr: => F[B]): F[B] =
if (arr == null || arr.length == 0) default else expr
}
让我们创建一个返回Option的实现:
implicit def optionNullGuard[F[X] <: Option[X]]: NullGuard[F] = new NullGuard[F]() {}
上面的代码确实可以编译,但是下面的尝试不使用上面的类型类:
def returnsOption[F[_], A, B](arr: Array[A])(implicit ng: NullGuard[F]): Option[B] = {
ng.nullGuard(arr, None) {
// sample work
if (arr.length % 2 == 0) Option(1) else None
}
}
我收到以下编译错误:
type mismatch;
found : None.type
required: F[?]
ng.nullGuard(arr, None){
我该如何使用它?如果有的话,我也愿意采用另一种方法。
答案 0 :(得分:5)
由于类型类没有任何抽象方法,因此可以用单个多态nullGuard
方法代替它:
def nullGuard[A, B]
(arr: Array[A], defaultValue: B)
(processArray: Array[A] => B)
: B = if (arr == null || arr.isEmpty) defaultValue else processArray(arr)
似乎也不再需要类型更高的类型参数F
:提供一种适用于任何B
作为返回类型的方法,而不仅仅是{{1} }。
这是您人为的,稍作修改的示例:如果数组中元素的数量为偶数,则从数组中提取最后一个值:
F[B]
输出:
for (example <- List[Array[Int]](null, Array(), Array(42), Array(1, 42))) {
val lastAtEvenIndex = nullGuard[Int, Option[Int]](example, Some(0)) {
a => if (a.size % 2 == 0) Option(a.last) else None
}
println(lastAtEvenIndex)
}
对于长度不均匀的数组,它返回Some(0)
Some(0)
None
Some(42)
,并将空/空数组视为将None
作为“最后一个”元素。
完整示例为单个代码段,其中0
为默认值:
None
打印:
def nullGuard[A, B]
(arr: Array[A], defaultValue: B)
(processArray: Array[A] => B)
: B = if (arr == null || arr.isEmpty) defaultValue else processArray(arr)
for (example <- List[Array[Int]](null, Array(), Array(42), Array(1, 42))) {
val lastAtEvenIndex = nullGuard[Int, Option[Int]](example, None) {
a => if (a.size % 2 == 0) Option(a.last) else None
}
println(lastAtEvenIndex)
}