Passing functions for all applicable types around

前端 未结 4 1537
广开言路
广开言路 2021-01-05 14:02

I followed the advice found here to define a function called square, and then tried to pass it to a function called twice. The functions are defined like this:



        
4条回答
  •  情深已故
    2021-01-05 15:03

    Your problem is that square isn't a function (ie. a scala.Function1[T, T] aka (T) => T). Instead it's a type parametrized method with multiple argument lists one of which is implicit ... there's no syntax in Scala to define an exactly equivalent function.

    Interestingly, your use of the Numeric type class means that the usual encodings of higher-ranked functions in Scala don't directly apply here, but we can adapt them to this case and get something like this,

    trait HigherRankedNumericFunction {
      def apply[T : Numeric](t : T) : T
    }
    
    val square = new HigherRankedNumericFunction {
      def apply[T : Numeric](t : T) : T = implicitly[Numeric[T]].times(t, t)
    }
    

    This gives us a higher-ranked "function" with its type parameter context-bounded to Numeric,

    scala> square(2)
    res0: Int = 4
    
    scala> square(2.0)
    res1: Double = 4.0
    
    scala> square("foo")
    :8: error: could not find implicit value for evidence parameter of type Numeric[java.lang.String]
       square("foo")
    

    We can now define twice in terms of HigherRankedNumericFunctions,

    def twice[T : Numeric](f : HigherRankedNumericFunction, a : T) : T = f(f(a))
    
    scala> twice(square, 2)
    res2: Int = 16
    
    scala> twice(square, 2.0)
    res3: Double = 16.0
    

    The obvious downside of this approach is that you lose out on the conciseness of Scala's monomorphic function literals.

提交回复
热议问题