[英]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#中編寫數字文字(例如2
或3.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.