gpt4 book ai didi

scala - 如何在scala中将函数定义为所有数字的通用函数?

转载 作者:行者123 更新时间:2023-12-04 17:33:38 26 4
gpt4 key购买 nike

I thought我需要在所有 Ordering[_] 中参数化我的函数类型。但这不起作用。

如何使以下函数适用于支持所需数学运算的所有类型,我怎么能自己发现这一点?

  /**
* Given a list of positive values and a candidate value, round the candidate value
* to the nearest value in the list of buckets.
*
* @param buckets
* @param candidate
* @return
*/
def bucketise(buckets: Seq[Int], candidate: Int): Int = {

// x <= y
buckets.foldLeft(buckets.head) { (x, y) =>
val midPoint = (x + y) / 2f

if (candidate < midPoint) x else y
}
}

我尝试命令单击 intellij 中的数学运算符( /+ ),但刚刚收到通知 Sc synthetic function .

最佳答案

如果您只想使用 Scala 标准库,请查看 Numeric[T] .在您的情况下,由于您想要进行非整数除法,因此您必须使用 Fractional[T] Numeric的子类.

以下是使用 scala 标准库类型类的代码的外观。请注意 Fractional延伸自 Ordered .在这种情况下这很方便,但它在数学上也不是通用的。例如。你不能定义 Fractional[T]Complex因为它没有订购。

def bucketiseScala[T: Fractional](buckets: Seq[T], candidate: T): T = {
// so we can use integral operators such as + and /
import Fractional.Implicits._
// so we can use ordering operators such as <. We do have a Ordering[T]
// typeclass instance because Fractional extends Ordered
import Ordering.Implicits._
// integral does not provide a simple way to create an integral from an
// integer, so this ugly hack
val two = (implicitly[Fractional[T]].one + implicitly[Fractional[T]].one)
buckets.foldLeft(buckets.head) { (x, y) =>
val midPoint = (x + y) / two
if (candidate < midPoint) x else y
}
}

但是,对于严肃的通用数值计算,我建议查看 spire .它提供了更精细的数字类型类层次结构。 Spire 类型类也是专门的,因此通常与直接使用原语一样快。

以下是使用 spire 的示例:
// imports all operator syntax as well as standard typeclass instances
import spire.implicits._
// we need to provide Order explicitly, since not all fields have an order.
// E.g. you can define a Field[Complex] even though complex numbers do not
// have an order.
def bucketiseSpire[T: Field: Order](buckets: Seq[T], candidate: T): T = {
// spire provides a way to get the typeclass instance using the type
// (standard practice in all libraries that use typeclasses extensively)
// the line below is equivalent to implicitly[Field[T]].fromInt(2)
// it also provides a simple way to convert from an integer
// operators are all enabled using the spire.implicits._ import
val two = Field[T].fromInt(2)
buckets.foldLeft(buckets.head) { (x, y) =>
val midPoint = (x + y) / two
if (candidate < midPoint) x else y
}
}

Spire 甚至提供从整数到 T 的自动转换如果存在 Field[T] ,因此您甚至可以像这样编写示例(几乎与非通用版本相同)。不过,我觉得上面的例子更容易理解。
// this is how it would look when using all advanced features of spire
def bucketiseSpireShort[T: Field: Order](buckets: Seq[T], candidate: T): T = {
buckets.foldLeft(buckets.head) { (x, y) =>
val midPoint = (x + y) / 2
if (candidate < midPoint) x else y
}
}

更新: spire 非常强大和通用,但也可能让初学者有些困惑。尤其是当事情不起作用时。这是一个 excellent blog post解释基本方法和一些问题。

关于scala - 如何在scala中将函数定义为所有数字的通用函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33076759/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com