簡體   English   中英

F# - 乘以float乘以int

[英]F# - multiply int by float

可能是一個愚蠢的問題,但我剛開始使用F#而且我遇到了一些問題。

說我有這樣的功能:

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):錯誤FS0001:此表達式應該具有類型

 int 

但這里有類型

 float 

因為我希望這個函數有點通用(即接受浮點數和整數),我不喜歡這個。 我的問題當然是:如何解決這個問題?

當您在F#中編寫數字文字(例如23.14 )時,編譯器會將其視為特定類型的值,因此使用數字文字的代碼不會是多態的。 您可以將輸入轉換為單一類型並使用該類型(如desco的答案中的float )或使用F#的更高級功能...

如果您將代碼標記為inline (這樣,編譯器可以表示其他約束並靜態解析它們),並且您只使用多態基元(具有其他靜態約束),則可以以多態方式編寫某些數值運算。

標准運算符在內inline函數中是多態的,而F#庫提供了一種獲取表示1和0(但不是2)的多態值的方法,但這足以編寫您想要的函數:

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

twoTimes 2
twoTimes 2.0

如果你想使這個更好,你可以定義一個數字文字(參見Daniel對早期StackOverflow問題的回答 ),然后你可以實際寫:

let inline twoTimes n = n * 2G

特殊數字文字2G被轉換為對NumericLiteralG函數的調用,它使用我上面使用的技術對指定數量的通用1值求和(因此對大數字效率不高!)有關更多信息,您還可以看到我的最近關於在F#中編寫通用數字代碼的文章。

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

如果你不害怕使用“小黑客”,這可能是有用的:

// 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

此構造不是類型安全的,因為類型檢查是在運行時完成的。 此外,報價相對較慢。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM