F#过于激进的类型推断?

Lee*_*ree 4 f# type-inference pattern-matching

因此,在做一些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
Run Code Online (Sandbox Code Playgroud)

显然,我的功能名为"p_dsqrt".但是,此函数要求输入定义了Sqrt方法,这种方法会破坏整个目的.我错过了一些类型约束,还是什么?

Gus*_*Gus 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 
Run Code Online (Sandbox Code Playgroud)

返回类型将始终与输入类型相同,并且所选sqrt的实现将取决于该类型.此选择将在编译时发生,这是与在运行时解析的匹配方法的主要区别.

如果我取出虚拟重载,它将与您的代码具有相同的问题:它将需要sqrt约束.