2009-10-01 18 views
9

私は、F#のunit systemと正しく相互作用する方法で、ユーザ定義の平方根関数(sqrt)を書くことがどのようにできるのだろうと考えました。ユニットセーフな平方根

 
let sqrt (x : float<'u^2>) = 
    let x' = x/1.0<'u^2> // Delete unit 
    (x ** 0.5) * 1.0<'u>  // Reassign unit 

しかし、これが原因一般的な単位を持つことが許されていないゼロ以外の定数に許可されていません:それはどうあるべきか

この機能を書く方法はありますか? sqrtが内蔵されているので問題なく動作しますか?

+1

関連の質問:(また、@kvbによって)http://stackoverflow.com/questions/1398611/f-ununit-reunit-inside-a-function – Benjol

答えて

6

ゼロ以外の一般定数を使用すると、ユニットのタイプシステムの安全性を破ることが非常に簡単になります(Andrew Kennedyのpapers参照)。私はあなたの最後の質問への答えは、通常の手段でそのタイプシグネチャでパラメトリック関数を定義することはできないはずであるという点で、sqrtが確かに魔法であるということです。

の場合:

let sqrt (x : float<'u^2>) = 
    let x' = (float x) ** 0.5 (* delete unit and calculate sqrt *) 
    ((box x') :?> float<'u>) 
6

@kvbは、より一般的に、権利である:しかし、それは(F#の現在のバージョンでは、少なくとも)ボクシングとキャストを利用することによって、あなたがやりたい可能ですあなたは非ユニット認識アルゴリズムを持っています(例えば、あなたが 'cube root'と書いているとします)。ユニットを置くには、適切な型シグネチャを持つ関数にアルゴリズムをラップして彼らが来るときにユニットを「キャスト・アウェイ」するために「フロート」し、途中で適切なユニットを「戻す」ためのボックス・アンド・ダウンキャスト・アプローチ。

RTMリリース(ベータ2以降)では、ボックスアンドダウンキャストアプローチは、これらのプリミティブの欠如を克服するための現在のビットであるため、F#には「追加バックユニット」用のプリミティブライブラリ関数があります。言語/ライブラリ。

+0

ありがとうございます - これらの新しいライブラリ関数(リンク)の名前を付けることができますか? – Dario

+3

LanguagePrimitivesモジュールの "val inline FloatWithMeasure:float - > float <'u>" – Brian

+0

そしてここにあります:http://msdn.microsoft.com/en-us/library/ee806527(VS.100).aspx – Benjol