具有更高种类类型和方差的 scala 类型类

标签 scala types typeclass higher-kinded-types

我有一个与此非常相似的问题:Scala higher kinded type variance

然而,这略有不同,因为它无法编译(scala 2.11.8)。

基本思想是获取提供的“事物”数组。如果数组为 null,则返回某种类型的默认值(例如 BooleanOptionList[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
  }

让我们创建一个返回选项的实现:

  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){

我怎样才能让它发挥作用?如果有的话,我也愿意接受另一种方法。

最佳答案

由于您的类型类没有任何抽象方法,因此可以将其替换为单个多态 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 作为返回类型的方法不需要花费任何费用,而是只是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)
}

打印:

None
None
None
Some(42)

关于具有更高种类类型和方差的 scala 类型类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51109947/

相关文章:

types - 在包含 nalgebra 的 VectorN 类型的结构上派生 Copy 时出错

dynamic - 静态类型绑定(bind)与动态类型绑定(bind)

haskell - 为什么 `Bits` 依赖于 `Num` ?

scala - 如何在第三方库中找出哪个后端用于 slf4j 日志记录?

Scala 工作表不评估 IntelliJ IDEA 2016.2 中的对象

Python:让 scipy 使用 numpy.float128 而不是 numpy.float64?

haskell - 类型类和重载,有什么联系?

haskell - Haskell 中的 float 、Ord 和 RealFloat

更高种类的 Scalacheck 问题 : diverging implicit expansion for type Arbitrary

scala - 为什么 SBT 给我一个类型不匹配错误?