Eri*_*rik 3 types scala typeclass higher-kinded-types
我有一个与此非常类似的问题:Scala更高的kinded类型方差
然而,这有点不同,嗯,它不编译(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
}
Run Code Online (Sandbox Code Playgroud)
让我们创建一个返回Option的实现:
implicit def optionNullGuard[F[X] <: Option[X]]: NullGuard[F] = new NullGuard[F]() {}
Run Code Online (Sandbox Code Playgroud)
以上编译,但以下尝试使用上述类型不会:
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
}
}
Run Code Online (Sandbox Code Playgroud)
我得到以下编译错误:
type mismatch;
found : None.type
required: F[?]
ng.nullGuard(arr, None){
Run Code Online (Sandbox Code Playgroud)
我怎样才能让它发挥作用?如果有的话,我也会接受另一种方法.
由于您的类型类没有任何抽象方法,因此可以用单个多态nullGuard
方法替换它:
def nullGuard[A, B]
(arr: Array[A], defaultValue: B)
(processArray: Array[A] => B)
: B = if (arr == null || arr.isEmpty) defaultValue else processArray(arr)
Run Code Online (Sandbox Code Playgroud)
更高的kinded类型参数F
似乎也不再需要:它不会花费你任何东西来提供一个适用于任何B
返回类型的方法,而不仅仅是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)
}
Run Code Online (Sandbox Code Playgroud)
输出:
Some(0)
Some(0)
None
Some(42)
Run Code Online (Sandbox Code Playgroud)
它返回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)
}
Run Code Online (Sandbox Code Playgroud)
打印:
None
None
None
Some(42)
Run Code Online (Sandbox Code Playgroud)