【问题标题】:Type inference problems in F#F# 中的类型推断问题
【发布时间】:2014-09-04 04:28:27
【问题描述】:

在 Visual Studio 中使用 F#,我发现自己必须明确地注释更多我想要或应该必须的类型。我知道一些解决这个问题的技术,特别是使用优秀的正向管道操作员。然而,在许多情况下,我无法避免这样做,其中一些似乎完全是错误的。

例如,我有类似以下 sn-p 的 F# 代码:

    let b = new pqBoard(this)
    let b2,steps = b.Solve()
    if b2.Solved() then 
        let cont = steps |> List.exists (fun (s : string) -> s.IndexOf("Contradiction") >= 0 )

第三行生成一条错误消息,提示上一行调用 Solve 方法返回的对中的第一个需要类型注释。但是该对的第二个元素(字符串列表)很好,不需要这样的注释。为什么类型检查器似乎可以确定该对中第二个的类型,而不是从单个调用返回的第一个?

如下修改第二行可以解决问题:

let (b2 : pqBoard,steps) = b.Solve()

为什么我必须明确键入第一个元素而不是第二个元素?

此外,在这种情况和许多其他情况下,VS 在工具提示中正确显示了推断类型。我假设 VS 编辑器在某种意义上是“猜测”,但我还没有看到它猜错了!

我发现必须明确提供类型而对为什么需要它们没有任何好主意,这令人沮丧和失望。任何帮助将不胜感激。

【问题讨论】:

  • 能否提供SolveSolved的实现?
  • 关于工具提示 - 有时 VS 会作弊并向后看,这在实际代码中是无法做到的。
  • 在不知道Solve 的定义的情况下,我猜它是一个通用函数。使用b2.Solved() 需要知道b2 的类型,但步骤实际上是由List.existss:string 注释的类型

标签: types f# inference


【解决方案1】:

如果没有看到pqBoardSolve 成员的定义,很难确定到底发生了什么,但您的示例中b2steps 之间的主要区别在于它们的使用方式 而不是它们的生成方式。

对于steps,它被传递到List.exists,对于某些'a,它必须取list<'a>,并且函数参数被显式注释为取string,因此类型检查器可以立即看到steps 必须是list<string> 类型。

对于b2,正在调用一个成员函数。可能有很多类型都有一个名为 Solved 的成员函数,而 F# 在不知道 b2 的类型的情况下无法解析正在调用哪些类型。

一般来说 - 虽然它不是通用的 - 在 F# 中使用 . 通常需要在前面的某个地方明确指定 . 左侧的事物的类型,而使用更“功能性”构造和类型不会。

【讨论】:

  • 非常感谢。我认为你关于它“不普遍”的评论是造成我困惑的主要原因,但我希望从现在开始我会少一些。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-25
  • 2013-05-05
  • 1970-01-01
  • 2023-03-17
  • 2016-04-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多