3

我今天玩了一点 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'

4

5 回答 5

6

类型推断使您的函数sq具有 type int -> int,因为编译器第一次看到您使用该函数时,您将其传递给一个整数。因此它假定这sq是一个接受整数的函数,并且根据函数 ( x * x) 的定义,它也返回一个整数。

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

let inline sq x = x * x

这样,您的函数的主体每次都会在调用站点内联,因此使用内联sq函数与每次使用时都替换它的主体相同。

这种方法有它的缺点,我认为你看到这个问题会很有趣。

于 2013-07-20T13:34:45.510 回答
2

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

let inline sq x = x * x
于 2013-07-20T13:34:09.867 回答
2

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

于 2013-07-20T15:21:14.167 回答
1

这是绑定如何实现的限制。有 2 种选择。

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

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

于 2013-07-20T13:33:51.840 回答
1

默认的函数let sq x = x * x有 type int -> int

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

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

于 2013-07-20T13:23:52.840 回答