2012-05-30 11 views
7

おそらく愚かな質問ですが、私はちょうどF#で始まったばかりですが、少し問題があります。F# - floatで整数を掛ける

は、私はこのような機能を持っていると言う:

let multiplyByTwo x = x * 2 

私はこのように、これを呼び出すとき:

let result = multiplyByTwo 5 

すべてが大丈夫です、私はそれを呼び出すと、結果は10

ですこのように:

let result = multiplyByTwo 2.5 

私は結果として5または5.0を得ることを期待しています。実際の結果は次のとおりです。

let result = multiplyByTwo 2.5 ;;
--------------------------------- ^^^

stdin(4,28):error FS0001:この式は、ここではタイプ

int  

しかし、私は、この関数はやや一般的なことがしたいので(つまり、浮動小数点数と整数の両方を受け入れる)

float 

型を持つことが期待された、私はこれが好きではありません。もちろん私の質問:どのようにこれを解決するのですか?

+0

私はF#についてはよく分かりませんが、あなたの関数の '2'はintと見なされていますが、xがintであることを期待しています。 – RedEyedMonster

+0

私はF#で始まったときに 'float'と' int'の 'incompatibility'が本当にバグしていましたが、数年後には、ゆっくりとさまざまな型として考えるようになりました。しばしば、私は本当に*ほしいものを自分自身に尋ねることを余儀なくされました。 – Benjol

+0

これは言語上の欠陥だと私は考えています。私は実数を扱いたいときに浮動小数点数を使用し、性能や精度については気にしません。 –

答えて

12
let inline mulBy2 x = (float x) * 2.0 

let a = mulBy2 3 // 6.0 : float 
let b = mulBy2 2.5 // 5.0 : float 
let c = mulBy2 "4" // 8.0 : float 
+0

私はこの方法が最もクリーンな方法であることを発見しました。良い解決策のように見えます。私はまだ 'インライン'のキーワードを完全に理解していません(入力を解析するように見えますが、使用する時期と使用しない時期はわかりません)。 –

+1

MSDNから: "インライン修飾子がなければ、型推論は関数に特定の型、この場合はintを強制しますが、インライン修飾子では、静的に解決された型パラメーターを持つことも推測されます。 floatへの変換をサポートするすべての型を受け入れます。 –

14

F#で数字リテラル(たとえば、2または3.14)を書き込むと、コンパイラはこれを特定の型の値として扱います。したがって、数値リテラルを使用するコードは多態的ではありません。入力を単一のタイプに変換し、そのタイプ(例えば、答えのfloat)を使用するか、F#のより高度な機能を使用することができます。

特定の数値演算は、多項式で書く​​ことができます。コードはinline(この方法では、コンパイラは追加の制約を表すことができ、それらを静的に解決できます)とポリモーフィックなプリミティブ(静的な制約が追加されている)を使用するだけです。

標準演算子はinline機能でpolymorpicであり、F#のライブラリは、多型1を表す値と0(ではないが2)を取得する方法を提供し、それはあなたが望んでいた機能を記述するだけで十分です:

let inline twoTimes n = 
    let one = LanguagePrimitives.GenericOne 
    n * (one + one) 

twoTimes 2 
twoTimes 2.0 

場合あなたは、これはよりよい、あなたが(Daniel's answer to earlier StackOverflow questionを参照)数値リテラルを定義することができるようにしたいと、あなたは実際には書くことができます。特別な数値リテラル2Gがへの呼び出しに変換され

let inline twoTimes n = n * 2G 

関数NumericLiteralG上記で使用した手法を使用して、指定された総数1の値を合計します(したがって、大量には効率的ではありません!)。詳細は、最近の記事writing generic numeric code in F#を参照してください。

+0

私がデコの答えを受け入れたのは、それが一番簡単な解決策でしたが、すばらしい投稿でした! Btw、私はあなたのウェブサイトであなたがDon Symeの学生の一人であることを読みました。 –

+0

ニース。私は ''答え "は文字通りを取り除く何かになると思っていましたが、どうやってそれを行うのかなぁ。 –

+0

@LeonCullens結果が 'float'であれば幸いですが、@descoの答えが最適です。 Don Symeは実際にはまだ私の(第2の)PhD監督者です:-)。 –

-1

あなたはこれで詰め込まれていると思います。型は2がintであることに基づいて推論され、2を使用できます。0、または2fですが、結果はすべて浮動小数点になります。

彼のもののチュートリアルを深く理解しなければならないと思いますが、私はそれほど助けません。

-1

あなたは「少しハック」を使用して恐れていない場合、これは便利かもしれません:

// Copied from Core.LanguagePrimitives.IntrinsicFunctions.retype 
[<NoDynamicInvocation>] 
let inline retype (x:'a) : 'b = (# "" x : 'b #) 

let inline multiplyByTwo (x:'a) = x * (retype 2:'a) 

// use 
let result1 = multiplyByTwo 5 // 10 
let result2 = multiplyByTwo 2.5 // 5.0 

型チェックは実行時に行われているので、この構築物は、タイプセーフではありません。また、引用は比較的遅いです。

関連する問題