【问题标题】:Scala: How to write generic function on sortable collection with arithmetic elementsScala:如何使用算术元素在可排序集合上编写通用函数
【发布时间】:2016-12-18 20:29:50
【问题描述】:

我有以下 Scala 函数,

def isValid(xs: Array[Int]): Boolean = {
  val List(x, y, z) = xs.sorted.toList
  x + y > z
}

当我将输入类型更改为List[Double] 时,这仍然有效。我希望它能够与通用集合以及可以比较和添加的任何元素一起使用。

编辑:这是我目前拥有的更通用的。不幸的是,它要求我指定泛型参数。

def isValid[N, S <% Seq[N]](xs: S)(implicit n: Numeric[N]): Boolean = {
  val Seq(x, y, z) = xs.sorted
  n.gt(n.plus(x, y), z)
}

// Ideally, I wouldn't have to specify the generic parameters.
listOfArray.filter(isValid[Int, Array[Int]])
listOfList.filter(isValid[Double, List[Double]])

【问题讨论】:

  • “使用通用集合”是什么意思Array[T] 是一个通用集合。
  • @YuvalItzchakov,我的意思是我想对容器本身进行参数化,而不仅仅是容器的元素,例如如果可能的话,我希望它可以与 ArrayList 以及其他容器一起使用。

标签: scala generics


【解决方案1】:

你可以使用Numerics:

  • 它扩展了Ordering,因此您可以在您的收藏中调用.sorted
  • 它实现了.plus.gt 运算符

用法:

scala> def isValid[N](xs: Seq[N])(implicit ev: Numeric[N]): Boolean = {
         val x::y::z::Nil = xs.sorted.toList
         ev.gt(ev.plus(x, y), z)  // same as 'x + y > z'
       }
isValid: [N](xs: Seq[N])(implicit ev: Numeric[N])Boolean

然后:

scala> isValid(List(1, 2, 3))
res0: Boolean = false

scala> isValid(List(1d, 2d, 3d))
res1: Boolean = false

scala> isValid(List(1L, 2L, 2L))
res2: Boolean = true

【讨论】:

  • 我明白了。我仍在尝试x + y &gt; z,而不是使用ev 中的方法。这让我更接近于我正在寻找的东西,但我仍然想用ListArray 来调用它,而且看起来没有从ArraySeq 的隐式转换。也许我可以提供一个。让我试试。
【解决方案2】:

sortedSeqLike 中声明,因此您可以只需要Seq

  import Numeric.Implicits._
  import Ordering.Implicits._

  def isValid[N: Numeric](xs: Seq[N]): Boolean = {
    val Seq(x, y, z) = xs.sorted
    x + y > z
  }

【讨论】:

  • 不幸的是,在这种情况下我得到错误:类型不匹配; found : N required: String x + y > z ^ 发现一个错误
  • @您的代码中是否包含了我的示例中的imports?
猜你喜欢
  • 2012-04-08
  • 1970-01-01
  • 2021-03-21
  • 1970-01-01
  • 1970-01-01
  • 2019-07-12
  • 2018-01-17
  • 1970-01-01
  • 2015-11-30
相关资源
最近更新 更多