printfn "f1()" f1在 FSI 中绑定(bind)为 *bind f1*-6ren">
gpt4 book ai didi

generics - 为什么显式泛型函数值与类似的非泛型绑定(bind)不同?

转载 作者:行者123 更新时间:2023-12-04 18:43:23 25 4
gpt4 key购买 nike

让我们取一个简单的函数值f1 :

let f1 = printfn "*bind f1*"; fun () -> printfn "f1()"
f1在 FSI 中绑定(bind)为
*bind f1*
val f1 : (unit -> unit)

并且,被调用,行为符合预期
> () |> f1 |> f1;;
f1()
f1()
val it : unit = ()

现在让我们取一个类似的函数值,但显式通用 f2<'a> :
let f2<'a> = printfn "*bind f2*"; fun () -> printfn "f2()"
f2在 FSI 中绑定(bind)为
val f2<'a> : (unit -> unit)

没有任何 *bind f2*输出任何内容,但随后被调用,在每个 f2 上输出它调用:
> () |> f2 |> f2;;
*bind f2*
f2()
*bind f2*
f2()
val it : unit = ()

我的问题是:这种观察到的差异可能是什么原因?

最佳答案

F# 通常不允许创建泛型值,因为这会引入“值限制”困难(也就是说,您不能创建泛型的语法值,即使它是返回函数的代码)。所以,你的 f2不应该被允许,但是...

该规则有一个异常(exception)——拥有像 List.empty 这样的通用值通常很有用。因此,如果您声明一个带有显式泛型类型参数的值,它实际上会被编译成一个返回结果的函数。

这正是您的示例中发生的情况:

let f2<'a> = printfn "*bind f2*"; fun () -> printfn "f2()"

在这里, f2是一个泛型值(尽管它实际上并没有在任何地方使用类型参数),但它有一个显式的泛型类型参数,因此它实际上被编译成一个每次调用的方法 f2被访问并返回结果(函数 unit -> unit )

我在规范中找不到任何明确的解释,但有一个 good MSDN article (参见“案例 4”)以及 blog by former F# team member .

关于generics - 为什么显式泛型函数值与类似的非泛型绑定(bind)不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19627496/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com