4

したがって、プロジェクトオイラーの問題のいくつかを実行する際に、整数値(int、long、bigintなど)の平方根を取得できるようにしたいのですが、Sqrtは浮動小数点値に対してのみ定義されています。だから私は自分の小さなニュートンラプソンアルゴリズムを書いてきました、そしてそれは私が必要とするものに対して十分に正確です。ただし、浮動小数点値に対して組み込みのsqrt関数を呼び出せるようにしたいと思います。だから私はこのようなものを書いた:

let inline dsqrt x =
    match box x with
    | :? float -> sqrt x
    | :? float32 -> sqrt x
    | _ -> p_dsqrt x

私の関数は、明らかに「p_dsqrt」という名前です。ただし、この関数では、入力にSqrtメソッドが定義されている必要があります。これにより、目的全体が無効になります。タイプの制約がありませんか、それとも何ですか?

4

2 に答える 2

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の実装はそのタイプによって異なります。この選択はコンパイル時に行われます。これは、実行時に解決されるmatchメソッドとの主な違いです。

ダミーのオーバーロードを削除すると、コードと同じ問題が発生します。sqrt制約が必要になります。

于 2012-09-24T21:11:35.800 に答える
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これにより、の可能なタイプが制限されますxfloat変更したコードでは、またはへの強制が成功した結果に新しい識別子をバインドするfloat32ため、のタイプに制約はありませんx

于 2012-09-24T20:54:36.750 に答える