首页 > 解决方案 > 处理“统一时生成的类型将是无限的”

问题描述

let rec bind x f = f x |> bind bind "Hello World" (fun x -> x.toUpper()) printf "%s"

上面的代码片段会导致此错误“统一时生成的类型将是无限的”。

编译器的建议:“基于此程序点之前的信息查找不确定类型的对象。在此程序点之前可能需要类型注释来约束对象的类型。这可能允许解析查找。”

正如编译器所说,添加类型注释将解决此问题。您将如何编写满足编译器的类型注释?

这可能会有所帮助。由于 Javascript 更宽容且不会抱怨,因此您可以查看将同一段代码翻译成 JS 的工作示例。

const bind = x => f => bind(f(x))

bind("Hello World")
(x => x.toUpperCase())
(console.log)

标签: recursionf#bind

解决方案


问题是bind您尝试定义的函数没有可以在标准 F# 中表达的类型。你想要一个类型看起来像这样的函数:

'A -> ('A -> 'B) -> ('B -> 'C) -> ('C -> 'D) -> ('D -> 'E) -> ....

换句话说,该bind函数应该接受输入和应用于它们的一系列函数,但您并没有限制该序列的长度。标准的 F# 类型系统没有表达这一点的方式,因此人们通常使用其他模式。在您的情况下,它将是|>操作员。与您的 相比bind,您必须|>重复编写,但这通常没问题:

"Hello World" 
|> (fun x -> x.ToUpper()) 
|> printf "%s"

也就是说,我认为您的示例选择不当,我只想写:

printf "%s" ("Hello world".ToUpper())

最后,bind由于 F# 静态成员约束,可以使用重载来定义类似函数的东西。这些方面的东西,但是|>是做你的例子说明的事情的惯用和干净的解决方案。


推荐阅读