3

int64をサポートしないのはなぜLanguagePrimitives.DivideByIntですか? 次のように書くのはかなり自然だと思いました:

let inline DivBy2 n = LanguagePrimitives.DivideByInt n 2
let res = DivBy2 100L

しかし、コンパイラはそれを言いint64 doesn't support the operator DivideByIntます.

私はチートを試みました:

type System.Int64 with 
    static member DivideByInt (n: System.Int64) (d: int) = n / (int64 d)

しかし、うまくいきません。

int64 を int で一般的に除算するにはどうすればよいですか?

4

5 に答える 5

7

F#のソースコードを見ると、int64型が関数DivideByIntに含まれていません。理由はわかりません。

次のような別のジェネリック関数を定義できます。

open LanguagePrimitives
type DivExtension = DivExtension of int with
    static member inline (=>) (x             , DivExtension y) = DivideByInt x y
    static member        (=>) (x:int64       , DivExtension y) = x / (int64 y)
    static member        (=>) (x:DivExtension, DivExtension y) = x

let inline DivByInt x y = x => DivExtension y

DivideByIntまたは、元の関数をシャドウすることもできます。

let inline DivideByInt x y = x => DivExtension y

さらにオーバーロードを追加することもできることに注意してください(つまり、intの場合)。この場合、正しい署名を推測するために最後の「ダミー」オーバーロードは必要ありません。

于 2012-03-02T06:44:50.277 に答える
3

Don Syme から (fsbugs の電子メール経由で) 回答を受け取りましMutliplyByIntDivideByInt:

ドンの答え:

この演算子は、「Seq.averageBy」などをサポートするために存在します。これは、カウントによる合計の疑似精密除算を表します。そのために必要な範囲を超えてメカニズムを拡張しませんでした。

そのため、このメカニズムの目的を誤解しているようです。int64しかし、なぜfor がサポートされていないのかはまだわかりませんDivideByInt。つまり、int64型に対する一般的な操作が制限されているということです。プリミティブ型ではないのに int64 がプリミティブ型のように見えるので、おそらく私は混乱しています。AndDivideByIntはプリミティブ型に対してのみ定義されているため、サポートされていません。

于 2012-03-08T09:31:54.503 に答える
2

ご指摘のとおり、DivideByInt主に をサポートするために存在しSeq.averageByます。整数型がサポートされていないという事実は、私には理にかなっています。なぜなら、の平均は である[1;2]べきであり1.5、そうではないから1です (これは、DivideByInt実装によって得られるものです)。これにより、入力を浮動小数点数に変換する必要があり、期待される答えが得られます。

于 2012-03-08T14:54:54.960 に答える
1

このように定義できますか?

let inline DivBy2 n = 
  let one = LanguagePrimitives.GenericOne
  n / (one + one)
于 2012-03-02T05:35:08.117 に答える
0

私は明らかにここでのパーティーに遅れていますが、なぜdivBy2関数を作成したいのかを知ることは興味深いでしょう. ここには 2 つの問題があり、ニーズによっては、そのうちの 1 つを解決するだけで十分な場合があります。

最初の問題は、 がないことLanguagePrimitives.GenericTwoです。これは簡単に修正できますが、2 以外の除数に対して特定の除算関数を定義したい場合、このソリューションの使用は限定されます。

let inline divBy2 n =
    n / (LanguagePrimitives.GenericOne + LanguagePrimitives.GenericOne)

入力を減らすために、変数に割り当てることができLanguagePrimitives.GenericOneます。これは、除数の大きさが大きくなるにつれてより便利になります。

let inline divBy4 n =
    let one = LanguagePrimitives.GenericOne
    let two = one + one
    n / (two + two)

このソリューションは、一般的な関数を作成する場合にも役に立ちません。「カスタム」の方法は

let inline divBy divisor dividend = dividend / divisor

これを部分関数アプリケーションで使用して、たとえば次のようにバイトのリストを半分にすることができます。

let halfBytes = [ 1uy .. 10uy ] |> List.map (divBy 2uy)

しかし、もっとうまくやることができます。この問題は、減算を含むすべての非可換演算子に適用されます。それを回避するために、定義できます

let flip f a b = f b a

これにより、たとえば

let scaledInThousands = [ 0m .. 500m .. 3000m ] |> List.map (flip (/) 1000m)
let decrementedIntegers = [ 1 .. 10 ] |> List.map (flip (-) 1)

必要に応じて、divBy 関数を定義することもできます。

let inline divBy n = flip (/) n
let halfInts = [ 1 .. 10 ] |> List.map (divBy 2)
let halfLongs = [ 1L .. 10L ] |> List.map (divBy 2L)
let fifthLongs = [ 1L .. 10L ] |> List.map (divBy 5L)
let oneThroughTenOverPi = [ 1.0 .. 10.0 ] |> List.map (divBy System.Math.PI)
于 2014-08-18T20:24:09.920 に答える