因此,在执行一些Project Euler问题时,我希望能够取整数值的平方根(int,long,bigint等),但Sqrt仅定义为浮点值。所以我一直在编写我自己的小Newton-Raphson算法,它对于我需要的东西来说非常准确。但是,我希望能够在浮点值上调用内置的sqrt函数。所以我写了这样的话:
let inline dsqrt x =
match box x with
| :? float -> sqrt x
| :? float32 -> sqrt x
| _ -> p_dsqrt x
显然,我的功能名为“p_dsqrt”。但是,此函数要求输入定义了Sqrt方法,这种方法会破坏整个目的。我错过了一些类型约束,还是什么?
答案 0 :(得分:6)
如果您想使用匹配,则不需要inline关键字,但如果您想使用内联函数和"帽子类型",请使用重载而不是匹配:
type Sqrt = Sqrt with
// Dummy overload in order to get the right types inferred (will never reach here)
static member inline ($) (Sqrt, _:^t when ^t:null and ^t: struct) = id
// Existing sqrt
static member inline ($) (Sqrt, x:'a) :'a = sqrt x
// Your Newton-Raphson based sqrt's
static member ($) (Sqrt, x:int ) = sqrtForInt x
static member ($) (Sqrt, x:bigint) = sqrtForBigInt x
let inline sqrt (x:'t) :'t = Sqrt $ x
返回类型将始终与输入类型相同,并且所选sqrt的实现将取决于该类型。此选择将在编译时发生,这是与在运行时解析的匹配方法的主要区别。
如果我取出虚拟重载,它将遇到与代码相同的问题:它将需要sqrt约束。
答案 1 :(得分:3)
我想你可能想要这个,而不是:
let dsqrt x =
match box x with
| :? float as f -> sqrt f |> box :?> 'a
| :? float32 as f -> sqrt f |> box :?> 'a
| _ -> p_dsqrt x
您的代码存在的问题是您直接调用sqrt x
,这会限制x
的可能类型。在我修改过的代码中,我将新标识符绑定到成功强制的结果为float
或float32
,因此这不会对x
的类型施加任何约束。