为什么不能使用不同类型的参数两次使用相同的函数?

时间:2013-07-20 13:19:02

标签: f# inline type-inference

今天我和F#玩了一下,写道:

let sq x = x * x

let i = sq 3
let d = sq 3.0

如果删除第三行或第四行,则编译,但如果两者都存在则不编译。

我收到错误This expression should have type 'int', but has type 'float'

5 个答案:

答案 0 :(得分:6)

类型推断有效,因此函数sq的类型为int -> int,因为第一次编译器看到你使用该函数时,会传递一个整数。因此它假定sq是一个取整数的函数,并且根据函数(x * x)的定义,它也返回一个整数。

在F#中定义一个完全通用的算术函数有点复杂,但一种方法是创建函数inline,如下所示:

let inline sq x = x * x

这样,每次在呼叫站点都会内联函数体,因此使用内联sq函数将与每次使用时替换它的正文相同。

这种方法有它的缺点,我认为看到this question会很有趣。

答案 1 :(得分:2)

自定义函数不能重载。在您的特定情况下,您可以使用inline,它在编译时内联函数体,因此可以选择适当的*实现,例如

let inline sq x = x * x

答案 2 :(得分:2)

其他答案是正确的,但它们忽略了拼图的一个重要部分:事实上,在F#中,没有隐式转换,例如,int和浮点数。这就是为什么你的第二个调用实际上是用float参数调用一个不同的,不存在的重载的原因。

答案 3 :(得分:1)

默认情况下,let sq x = x * x函数的类型为int -> int

如果将它放在let d = sq 3.0的上下文中,F#编译器会将其类型推断为float -> float

无论如何,此函数只能有一个类型签名,int->intfloat->float

答案 4 :(得分:1)

这是绑定实现方式的限制。有两种选择。

首先,在声明中添加内联。

其次,在类中使用成员绑定并覆盖不同的类型。