5

我在 F# 中编写了一个库¹,它提供了一些按位操作,我想确保尽可能多的函数是inlinelet 与静态类型参数的绑定(这允许我编写一个函数并将其用于int16int32,也许即使bignum开销很小)。这条路线在某些时候肯定会失败。所述库提供的一些功能有些复杂。

¹注意:我知道通过公共接口公开内联 let 绑定的问题。

但是,我想将其扩展到最大范围。现在,我正在尝试以这种形式编写人口计数算法,但遇到了一个问题。我不确定如何编码0x3333...出现在这些算法中的掩码,例如 。我可以使用一些额外的技巧来解决移位常量和类似问题。

我可以使用任何技巧,无论是通过 F# 的类型推断和静态类型参数,还是通过位旋转,以我想要的方式编写算法?有什么方法可以在静态通用函数中编码这些类型的常量吗?

一个更模糊的问题:我可以依靠一些具体的东西来充分利用静态类型参数,尤其是在数字的上下文中?例如,我大量使用GenericOneand GenericZero。还有更多这样的事情,我可能会错过吗?

4

1 回答 1

5

首先,您可以使用数字文字来避免丑陋的使用GenericOneand GenericZero。这是一个简短的例子:

module NumericLiteralG = begin
  let inline FromZero() = LanguagePrimitives.GenericZero
  let inline FromOne() = LanguagePrimitives.GenericOne
  let inline FromInt32 (n:int) =
        let one : ^a = FromOne()
        let zero : ^a = FromZero()
        let n_incr = if n > 0 then 1 else -1
        let g_incr = if n > 0 then one else (zero - one)
        let rec loop i g = 
            if i = n then g
            else loop (i + n_incr) (g + g_incr)
        loop 0 zero 
end

// Usage
let inline ten() = 10G
ten() + 1
ten() + 2L

其次,F# 似乎不支持通用的六进制数字文字。一个技巧是使用双反引号,以便您具有指示性名称:

let inline shift x = 
    let ``0x33333333G`` = 858993459G
    ((x >>> 2) &&& ``0x33333333G``) + (x &&& ``0x33333333G``)

// Usage
shift 20
shift 20L
shift 20uy

关于数字文字有一些很好的问题。如果你走这条路,我会提供一些参考:

于 2012-10-22T17:40:37.750 回答