【问题标题】:How do I implement a generic mathematical function in Scala如何在 Scala 中实现通用数学函数
【发布时间】:2010-10-29 22:47:45
【问题描述】:

我刚刚开始使用 Scala,而我认为应该很简单的事情却很难弄清楚。我正在尝试实现以下功能:

def square(x:Int):Int = { x * x }

这很好用,但如果我想让这个函数适用于任何类型的数字,我希望能够执行以下操作:

def square[T <: Number](x : T):T = { x * x }

这抱怨并说:错误:值*不是类型参数T的成员

我需要为此实现一个特征吗?

【问题讨论】:

    标签: scala polymorphism


    【解决方案1】:

    那是我在 Stack Overflow 或关于 Scala 中的first questions 之一。问题在于 Scala 保持与 Java 的兼容性,这意味着它的基本数字类型等同于 Java 的原语。

    问题在于 Java 原语不是类,因此没有允许“数字”超类型的类层次结构。

    说得更清楚一点,Java 以及因此 Scala 在Double+Int+ 之间没有任何共同点。

    Scala 最终绕过这个限制的方法是使用Numeric 及其子类FractionalIntegral,即所谓的类型类模式。基本上,你可以这样使用它:

    def square[T](x: T)(implicit num: Numeric[T]): T = {
        import num._
        x * x
    }
    

    或者,如果您不需要任何数字操作,但您调用的方法需要,您可以使用 context bound 语法进行类型声明:

    def numberAndSquare[T : Numeric](x: T) = x -> square(x)
    

    有关详细信息,请参阅我自己的问题中的答案。

    【讨论】:

    • 很好的解释。我不得不用谷歌搜索 Typeclass Pattern - 不知道它存在。谢谢。
    • 如果你有这个怎么办:def squareAddOne[T](x: T)(implicit num: Numeric[T]): T = { import num._; x * x + 1 }你如何将 Int 添加到 Numeric?
    • 哦,我想我的问题在这里得到了回答:stackoverflow.com/a/2388386/901263
    • @JohnPeterThompsonGarcés 是的。 zero and oneNumeric 常量,还有 fromInt。因为你可以否定并且你有一个,所以所有的“int”都是可用的,但你不能组合其他任何东西。
    【解决方案2】:

    您可以将square 定义为:

    def square[T: Numeric](x: T): T = implicitly[Numeric[T]].times(x,x)
    

    这种方法的优点是它适用于任何隐式转换为 Numeric[T] 的类型 T(即 Int、Float、Double、Char、BigInt、...,或您为其提供隐式转换)。

    编辑: 不幸的是,如果你尝试List(1,2,3).map(square) 之类的东西,你会遇到麻烦(具体来说,你会得到一个编译错误,比如“找不到 Numeric[T] 类型的证据参数的隐含值”。为了避免这个问题,你可以重载square 以返回一个函数:

    object MyMath {
       def square[T: Numeric](x: T) = implicitly[Numeric[T]].times(x,x)
       def square[T: Numeric]: T => T = square(_)
    }
    

    希望对类型推断器有更好理解的人能解释为什么会这样。

    正如 Derek Williams 在scala-user mailing list thread 中指出的那样,您也可以致电List(1,2,3).map(square(_))

    【讨论】:

      猜你喜欢
      • 2015-06-03
      • 2014-10-26
      • 2019-03-21
      • 2021-10-21
      • 1970-01-01
      • 1970-01-01
      • 2015-04-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多