【问题标题】:Scala pass generic numeric function as parameterScala将通用数值函数作为参数传递
【发布时间】:2017-12-03 16:34:54
【问题描述】:
def weirdfunc(message: String, f: (Int, Int) => Int){
            println(message + s" ${f(3,5)}")
          }

我有上面的功能。如何使函数f 对所有数值类型都是通用的?

【问题讨论】:

  • def weirdfunc[T : Numeric](message: String, f: (T, T) => T)

标签: scala generics types parameters numeric


【解决方案1】:

抱歉,您无法将其概括。调用者可以设置通用参数..而不是被调用函数..就像调用者传递函数参数一样。
但是,您可以使用 currying,以便将 Int 类型的“f”传递一次,然后传递不同的 Int 对。然后你可以传递 Double 类型的 'f',并传递不同的 Double 对。

  def weirdfunc[A](message: String, f: (A, A) => A)(x: A, y: A){
    println(message + s" ${f(x, y)}")
  }

  def g(x: Int, y: Int): Int = x * y
  val wierdfuncWithF = weirdfunc("hello", g) _
  wierdfuncWithF(3, 5)
  wierdfuncWithF(2, 3)

尤其是你想要的,因为它会破坏泛型规则。

【讨论】:

    【解决方案2】:

    你想要的被称为更高等级的类型(具体来说,等级 2)。 Haskell 支持这些类型,Scala 从 Haskell 那里获得了很多类型理论思想,但 Scala 还没有直接支持这个特定的特性。

    现在,问题是,通过一点黑魔法,我们可以让 Scala 做你想做的事,但是语法……不漂亮。在 Scala 中,函数始终是单态的,但您希望将多态函数作为参数传递。我们不能这样做,但我们可以传递一个看起来和行为都像函数的多态函数类对象。这个物体会是什么样子?

    trait NumFunc {
      def apply[A : Numeric](a: A, b: A): A
    }
    

    这只是一个定义多态apply 的特征。现在我们可以定义您真正想要的功能了。

    def weirdfunc(message: String, f: NumFunc) = ???
    

    正如我所提到的,这里的问题是语法非常糟糕。要调用它,我们不能再只传入一个函数。我们必须创建一个NumFunc 并将其传入。本质上,从类型理论的角度来看,我们必须向编译器证明我们的函数适用于所有数字A。比如调用简单的weirdfunc,只接受整数并传递加法函数就很简单了。

    weirdfunc("Some message", (_ + _))
    

    但是,要调用适用于所有数字类型的“特殊”weirdfunc,我们必须编写这个烂摊子。

    weirdfunc("Hi", new NumFunc {
      override def apply[A : Numeric](a: A, b: A): A = {
        import math.Numeric.Implicits._
        a + b
      }
    })
    

    而且我们不能用隐式转换来隐藏它,因为正如我之前提到的,函数是单态的,所以任何从函数类型出来的转换都是单态的。

    底线。可能吗?是的。在可读性和可用性方面值得付出代价吗?应该不会吧。

    【讨论】:

      【解决方案3】:

      Scala 对此有一个类型类,因此使用上下文绑定和标准库很容易实现。

      def weirdfunc[T: Numeric](message: String, x: T, y: T, f: (T, T) => T) {
        println(message + s" ${f(x, y)}")
      }
      
      def test[T](a: T, b: T)(implicit ev: Numeric[T]): T = ev.plus(a, b)
      
      weirdFunc[Int]("The sum is ", 3, 5, test)
      // The sum is 8
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-11-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-11
        • 1970-01-01
        • 2015-03-22
        相关资源
        最近更新 更多