F# 函数组合更改基函数类型

F# function composition changes base function types

我正在研究 this F# wikibook,我对在链接页面的功能组合部分看到的内容感到困惑。

我能想到的最简单的例子如下:

// int -> int
let f x = x + x
// float -> float
let g x = x + 1.0

这很好。我很容易理解这些函数的类型,我可以在 fsi 中 运行 它们并确认它们采用我上面提到的类型的 return 值。

如果我添加以下行,然后我看到了我不太确定我理解的变化。

// equivalent to f (g x)
let fog = f << g

按照我的理解,它不应该起作用,因为 f 需要一个 int,但是 g return 是一个 float。

如果我在 fsi 中定义这个组合,我会得到预期的类型错误。如果我将所有这些放在一个 .fsx 文件中并将整个文件发送给 fsi,则 f 的签名变为 float -> float.

我对以下内容感到困惑:

我已尝试搜索,但目前我还不够了解,无法有效地找到这些问题的答案。如果你能帮我指出解决这些问题的部分,我会很高兴 RTFM。

混淆来自这样一个事实,即虽然 (+) 运算符是通用的,但它有一个默认类型 int 因此取决于您正在编译的其余代码,它将适用或不是默认类型。

这意味着如果你只给出类型推断:

let f x = x + x

它将被推断为 int 但它可能是支持 (+) 运算符的任何其他数字类型,但由于您没有提供更多信息,它使用默认值。

请注意,F# 必须为此函数选择一种类型才能在 .NET 类型系统中进行编码,除非您定义它 inline,否则它将保持通用。

let inline f x = x + x

// val inline f :  x: ^a ->  ^b when  ^a : (static member ( + ) :  ^a *  ^a ->  ^b)

现在,如果您在使用函数 f 的那一行编译其他代码,类型推断可以分析类型并获得更准确的候选者。

这是一个更简单的示例,打开一个新脚本并粘贴此代码:

let f x = x + x
let v = f 1.

现在通过在每一行按 CTRL + ' 逐行执行,它将推断 int 并在第二行失败。

但现在 select 整个脚本并按 ALT + ENTER,它将编译并且 f 将被推断为 float 因为它是能够使用以下使用 f.

的行的信息