为什么 F# 的类型推断如此变化无常?
F# 编译器似乎以(相当)严格的从上到下、从左到右的方式执行类型推断。这意味着您必须做一些事情,例如在使用之前放置所有定义,文件编译的顺序很重要,并且您往往需要重新排列内容(通过 |>
或您拥有的东西)以避免显式类型注释。
使其更加灵活有多困难?F# 的未来版本是否计划这样做?显然这是可以做到的,因为 Haskell(例如)没有这样的限制,并且具有同样强大的推理能力。 F# 的设计或意识形态是否有任何本质上的不同导致了这种情况?
The F# compiler appears to perform type inference in a (fairly) strict top-to-bottom, left-to-right fashion. This means you must do things like put all definitions before their use, order of file compilation is significant, and you tend to need to rearrange stuff (via |>
or what have you) to avoid having explicit type annotations.
How hard is it to make this more flexible, and is that planned for a future version of F#? Obviously it can be done, since Haskell (for example) has no such limitations with equally powerful inference. Is there anything inherently different about the design or ideology of F# that is causing this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
关于“Haskell同样强大的推理”,我不认为Haskell必须处理
也就是说,我认为 F# 必须处理一些 Haskell 不处理的困难事情。 (几乎可以肯定,Haskell 必须处理一些 F# 不处理的难题。)
正如其他答案所提到的,大多数主要 .NET 语言都将 Visual Studio 工具作为主要的语言设计影响(参见例如 LINQ 如何具有“ from ... select" 而不是 SQL-y "select... from",其动机是从程序前缀获取智能感知)。智能感知、错误曲线和错误消息可理解性都是影响 F# 设计的工具因素。
很可能做得更好并推断更多(在不牺牲其他体验的情况下),但我不认为这是我们未来版本的语言的首要任务之一。 (Haskeller 可能会认为 F# 类型推断有点弱,但他们的数量可能会被认为 F# 类型推断非常强的 C# 人所超越。:))
以不间断的方式扩展类型推断也可能很困难;在未来的版本中将非法程序更改为合法程序是可以的,但是您必须非常小心,以确保以前的合法程序不会在新的推理规则下更改语义,并且名称解析(对每种语言来说都是可怕的噩梦)很可能以令人惊讶的方式与类型推断变化进行交互。
Regarding "Haskell's equally powerful inference", I don't think Haskell has to deal with
That is, I think F# has to deal with some hard stuff that Haskell does not. (Almost certainly, Haskell has to deal with some hard stuff that F# does not.)
As is mentioned by other answers, most of the major .NET languages have the Visual Studio tooling as a major language design influence (see e.g. how LINQ has "from ... select" rather than the SQL-y "select... from", motivated by getting intellisense from a program prefix). Intellisense, error squiggles, and error-message comprehensibility are all tooling factors that inform the F# design.
It may well be possible to do better and infer more (without sacrificing on other experiences), but I don't think it's among our high priorities for future versions of the language. (The Haskellers may see F# type inference as somewhat weak, but they are probably outnumbered by the C#ers who see F# type inference as very strong. :) )
It might also be hard to extend the type inference in a non-breaking fashion; it is ok to change illegal programs into legal ones in a future version, but you have to be very careful to ensure previously-legal programs do not change semantics under new inference rules, and name resolution (an awful nightmare in every language) is likely to interact with type-inference-changes in surprising ways.
我认为 F# 使用的算法的好处是很容易(至少粗略地)解释它是如何工作的,所以一旦你理解了它,你就可以对结果有一些期望。
该算法总是有一些限制。目前,理解它们是很容易的。对于更复杂的算法,这可能很困难。例如,我认为您可能会遇到这样的情况:您认为算法应该能够推断出某些内容 - 但如果它足够通用以涵盖该情况,那么它将是不可判定的(例如可以永远循环)。
对此的另一个想法是,从上到下检查代码对应于我们阅读代码的方式(至少有时)。因此,也许事实上,我们倾向于以支持类型推断的方式编写代码,这也使得代码对人们来说更具可读性......
I think that the algorithm used by F# has the benefit that it is easy to (at least roughly) explain how it works, so once you understand it, you can have some expectations about the result.
The algorithm will always have some limitations. Currently, it is quite easy to understand them. For more complicated algorithms, this could be difficult. For example, I think you could run into situations where you think that the algorithm should be able to deduce something - but if it was general enough to cover the case, it would be non-decidable (e.g. could keep looping forever).
Another thought on this is that checking the code from the top to the bottom corresponds to how we read code (at least sometimes). So, maybe the fact that we tend to write the code in a way that enables type-inference also makes the code more readable for people...
http ://www.markhneedham.com/blog/2009/05/02/f-stuff-i-get-confused-about/#comment-16153
http://www.markhneedham.com/blog/2009/05/02/f-stuff-i-get-confused-about/#comment-16153
简短的回答是,F# 基于 SML 和 OCaml 的传统,而 Haskell 来自 Miranda、Gofer 等略有不同的世界。历史传统的差异是微妙的,但却是普遍存在的。这种区别在其他现代语言中也有类似的情况,例如类似 ML 的 Coq 具有相同的排序限制,而类似 Haskell 的 Agda 则没有相同的排序限制。
这种差异与惰性评估与严格评估有关。 Haskell 宇宙相信惰性,一旦你已经相信惰性,那么在类型推断之类的事情上添加惰性的想法就是理所当然的了。而在 ML 领域,只要需要惰性或相互递归,就必须使用 with、and、rec 等关键字来明确指出em> 等。我更喜欢 Haskell 方法,因为它会减少样板代码,但有很多人认为最好将这些事情明确化。
The short answer is that F# is based on the tradition of SML and OCaml, whereas Haskell comes from a slightly different world of Miranda, Gofer, and the like. The differences in historical tradition are subtle, but pervasive. This distinction is paralleled in other modern languages too, such as the ML-like Coq which has the same ordering restrictions vs the Haskell-like Agda which doesn't.
This difference is related to lazy vs strict evaluation. The Haskell side of the universe believes in laziness, and once you already believe in laziness the idea of adding laziness to things like type inference is a no-brainer. Whereas in the ML side of the universe whenever laziness or mutual recursion is necessary it must be explicitly noted by the use of keywords like with, and, rec, etc. I prefer the Haskell approach because it results in less boilerplate code, but there are a lot of folks who think it's better to make these things explicit.