F# - 乘以float乘以int

时间:2012-05-30 21:57:44

标签: f# functional-programming

可能是一个愚蠢的问题,但我刚开始使用F#而且我遇到了一些问题。

说我有这样的功能:

let multiplyByTwo x = x * 2

当我这样称呼时:

let result = multiplyByTwo 5

一切都很好,结果是10。

当我这样称呼时:

let result = multiplyByTwo 2.5

我希望得到5或5.0。但实际结果如下:

  

让result = multiplyByTwo 2.5 ;;
    --------------------------------- ^^^

     

stdin(4,28):错误FS0001:此表达式应具有类型

int     
     

但这里有类型

float

因为我希望这个函数有些通用(即接受浮点数和整数),我不喜欢这个。我的问题当然是:如何解决这个问题?

3 个答案:

答案 0 :(得分:14)

当您在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's answer to earlier StackOverflow question),然后你可以实际写:

let inline twoTimes n = n * 2G

特殊数字文字2G被转换为对NumericLiteralG函数的调用,该函数使用我上面使用的技术对指定数量的通用1值求和(因此对大型函数来说效率不高)数字!)有关详情,请参阅我最近关于writing generic numeric code in F#的文章。

答案 1 :(得分: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

答案 2 :(得分:-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

此构造不是类型安全的,因为类型检查是在运行时完成的。此外,报价相对较慢。