Scala 函数对象之间的隐式转换?

发布于 2024-11-03 03:17:27 字数 1630 浏览 1 评论 0原文

我正在尝试重新绑定 scala.math 中的一些函数来获取并返回 Float 对象而不是 Double 对象,以便我可以将它们绑定到一个函数注册器,该函数注册器与接受和返回Float对象的函数一起使用。我已经尝试过这个规则:

implicit def doubleFunc2floatFunc[T <: { def apply(x:Double):Double }] (func:T) = func(_:Float).floatValue

但它不起作用。编译器抱怨我的函数是 (Double)=>Float 而不是 (Float)=>Float。有人能指出我正确的方向吗?

编辑:我使用的代码如下:

package org.nathanmoos.magnificalc.exprtreelib.functions

import org.nathanmoos.magnificalc.exprtreelib.Functions
import scala.math._


object InternalFunctions
{
    implicit def float2double(x:Float) = x.doubleValue
    // need an implicit def doubleFunc2floatFunc
    implicit def double2float(x:Double) = x.floatValue
    def csc(x:Float):Float = 1f/sin(x)
    def sec(x:Float):Float = 1f/cos(x)
    def cot(x:Float):Float = 1f/tan(x)

    def registerAll() = {
        Functions.register("ln", log _)
        Functions.register("log", log10 _)
        Functions.register("sqrt", sqrt _)
        Functions.register("sin", sin _)
        Functions.register("cos", cos _)
        Functions.register("tan", tan _)
        Functions.register("csc", csc _)
        Functions.register("sec", sec _)
        Functions.register("cot", cot _)
        Functions.register("sinh", sinh _)
        Functions.register("cosh", cosh _)
        Functions.register("tanh", tanh _)
        Functions.register("acos", acos _)
        Functions.register("asin", asin _)
        Functions.register("atan", atan _)
    }
}

Functions.register 采用一个 String 作为函数的名称和一个函数对象将其与.

I am trying to re-bind some of the functions in scala.math to take and return Float objects rather than Double objects so that I can bind them to a function registrar that works with functions that take and return Float objects. I've tried this rule:

implicit def doubleFunc2floatFunc[T <: { def apply(x:Double):Double }] (func:T) = func(_:Float).floatValue

and it doesn't work. The compiler complains that my functions are (Double)=>Float rather than (Float)=>Float. Can anyone point me in the right direction?

EDIT: the code I am using this in is as follows:

package org.nathanmoos.magnificalc.exprtreelib.functions

import org.nathanmoos.magnificalc.exprtreelib.Functions
import scala.math._


object InternalFunctions
{
    implicit def float2double(x:Float) = x.doubleValue
    // need an implicit def doubleFunc2floatFunc
    implicit def double2float(x:Double) = x.floatValue
    def csc(x:Float):Float = 1f/sin(x)
    def sec(x:Float):Float = 1f/cos(x)
    def cot(x:Float):Float = 1f/tan(x)

    def registerAll() = {
        Functions.register("ln", log _)
        Functions.register("log", log10 _)
        Functions.register("sqrt", sqrt _)
        Functions.register("sin", sin _)
        Functions.register("cos", cos _)
        Functions.register("tan", tan _)
        Functions.register("csc", csc _)
        Functions.register("sec", sec _)
        Functions.register("cot", cot _)
        Functions.register("sinh", sinh _)
        Functions.register("cosh", cosh _)
        Functions.register("tanh", tanh _)
        Functions.register("acos", acos _)
        Functions.register("asin", asin _)
        Functions.register("atan", atan _)
    }
}

Functions.register takes a String for the function's name and a function-object to associate it with.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

云仙小弟 2024-11-10 03:17:27

我不知道到底发生了什么,但它首先检查函数的返回类型,如果无法解决则失败。但是,如果您确实使它能够修复返回类型,那么它会继续检查整个函数。

所以你可以通过创建两个隐式来做到这一点:

implicit def doubleToFloat(d: Double): Float = d.toFloat
implicit def doubleFunc2floatFunc(df : Double => Float) : Float => Float = (f : Float) => df(f)

I don't know what exactly is going on, but it first checks for the return type of the function, and then fails if it can't solve that. But if you do make it possible for it to fix the return type, then it proceeds to check the whole function.

So you can do it by creating two implicits:

implicit def doubleToFloat(d: Double): Float = d.toFloat
implicit def doubleFunc2floatFunc(df : Double => Float) : Float => Float = (f : Float) => df(f)
つ低調成傷 2024-11-10 03:17:27

这里不需要结构类型或者类型参数,

scala> implicit def doubleFunc2floatFunc(df : Double => Double) : Float => Float = (f : Float) => df(f).toFloat
doubleFunc2floatFunc: (df: (Double) => Double)(Float) => Float

那么在使用时,

scala> val f : Float => Float = scala.math.abs
f: (Float) => Float = <function1>

scala> f(-1.0)
<console>:8: error: type mismatch;
 found   : Double(-1.0)
 required: Float
   f(-1.0)
     ^

scala> f(-1.0f)
res1: Float = 1.0

There's no need for structural types or type parameters here,

scala> implicit def doubleFunc2floatFunc(df : Double => Double) : Float => Float = (f : Float) => df(f).toFloat
doubleFunc2floatFunc: (df: (Double) => Double)(Float) => Float

Then in use,

scala> val f : Float => Float = scala.math.abs
f: (Float) => Float = <function1>

scala> f(-1.0)
<console>:8: error: type mismatch;
 found   : Double(-1.0)
 required: Float
   f(-1.0)
     ^

scala> f(-1.0f)
res1: Float = 1.0
尛丟丟 2024-11-10 03:17:27

我认为根本问题(在我们删除预定义中已经存在的隐式、不必要的结构类型,然后将自己限制在未重载的数学函数之后)是弱一致性和 eta 扩展之间奇怪的类型推理交互。参数类型Float符合预期参数类型Double,因此不会触发函数类型的隐式转换;它针对结果类型启动,但为时已晚。它已经确定参数类型是Double。

scala> implicit def dd2ff(x: Double => Double): Float => Float = x => x
dd2ff: (x: (Double) => Double)(Float) => Float

scala> def dd(x: Double) = x
dd: (x: Double)Double

scala> val ff: Float => Float = (dd _)
<console>:9: error: type mismatch;
 found   : Double
 required: Float
       val ff: Float => Float = (dd _)
                                 ^

scala> val x = dd _
x: (Double) => Double = <function1>

scala> val ff: Float => Float = x
ff: (Float) => Float = <function1>

I think the underlying issue (after we remove implicits which are already in predef, unnecessary structural types, and then limit ourselves to math functions which aren't overloaded) is a weird type inference interaction between weak conformance and eta expansion. The parameter type Float conforms to the expected parameter type Double, and so the implicit conversion for the function type doesn't trigger; it kicks in for the result type, which is too late. It has already decided the parameter type is Double.

scala> implicit def dd2ff(x: Double => Double): Float => Float = x => x
dd2ff: (x: (Double) => Double)(Float) => Float

scala> def dd(x: Double) = x
dd: (x: Double)Double

scala> val ff: Float => Float = (dd _)
<console>:9: error: type mismatch;
 found   : Double
 required: Float
       val ff: Float => Float = (dd _)
                                 ^

scala> val x = dd _
x: (Double) => Double = <function1>

scala> val ff: Float => Float = x
ff: (Float) => Float = <function1>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文