Scala 函数对象之间的隐式转换?
我正在尝试重新绑定 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我不知道到底发生了什么,但它首先检查函数的返回类型,如果无法解决则失败。但是,如果您确实使它能够修复返回类型,那么它会继续检查整个函数。
所以你可以通过创建两个隐式来做到这一点:
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:
这里不需要结构类型或者类型参数,
那么在使用时,
There's no need for structural types or type parameters here,
Then in use,
我认为根本问题(在我们删除预定义中已经存在的隐式、不必要的结构类型,然后将自己限制在未重载的数学函数之后)是弱一致性和 eta 扩展之间奇怪的类型推理交互。参数类型Float符合预期参数类型Double,因此不会触发函数类型的隐式转换;它针对结果类型启动,但为时已晚。它已经确定参数类型是Double。
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.