5

いくつかのビット単位の操作を提供する F# でライブラリ¹ を作成しています。できるだけ多くの関数がinline静的な型パラメーターを持つ let バインディングであることを確認したいと考えています (これにより、1 つの関数を記述し、それをint16int32、およびおそらくbignumオーバーヘッドがほとんどない場合でも)。このルートは、ある時点で確実に機能しなくなります。上記のライブラリによって提供される機能の一部は、やや複雑です。

¹注: public インターフェイスを介してインライン let バインディングを公開する際の問題については承知しています。

ただし、これを可能な限り伸ばしたいと思います。現在、人口カウントアルゴリズムをこの形式で記述しようとしていますが、問題に直面しています。0x3333...たとえば、これらのアルゴリズムに表示されるマスクをエンコードする方法がわかりません。いくつかの余分なビットトリックを使用して、シフト定数などを回避できます。

F# の型推論と静的型パラメーターを使用するか、ビット操作を使用して、思いどおりにアルゴリズムを作成するために使用できるトリックはありますか? これらの種類の定数を静的ジェネリック関数でエンコードする方法はありますか?

より漠然とした質問: 特に数値のコンテキストで、静的型パラメーターを最大限に活用するために頼ることができる特定のものはありますか? たとえば、私は と を頻繁に使用GenericOneGenericZeroます。私が見逃したかもしれない、このようなものがもっとありますか?

4

1 に答える 1

5

まず、数値リテラルGenericOneを使用して、 andの醜い使用を避けることができます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# は一般的な16 進数リテラルをサポートしていないようです。1 つのトリックは、2 つのバッククォートを使用して、わかりやすい名前を付けることです。

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

// Usage
shift 20
shift 20L
shift 20uy

数値リテラルに関するSOに関するいくつかの良い質問があります。あなたがそのルートに行く場合に備えて、いくつかの参考文献を示します。

于 2012-10-22T17:40:37.750 に答える