【问题标题】:Unknown need for type annotation or cast未知需要类型注释或强制转换
【发布时间】:2011-01-16 08:52:58
【问题描述】:

我知道我必须在这里遗漏一些非常明显的东西。 B.GetInstance().Call() 生成错误:根据此程序点之前的信息查找不确定类型的对象。在这个程序点之前可能需要一个类型注释来约束对象的类型。这可能会解决查找问题。

我正在使用 v1.9.9.9。

type A() =
    member x.Call() = B.GetInstance().Call()

and B() =
    static member GetInstance() = new B()
    member x.Call() = ()

我刚刚发现这行得通:(B.GetInstance() :> B).Call()

知道为什么需要演员表吗?

【问题讨论】:

    标签: f# type-inference


    【解决方案1】:

    当您有一组要推断其类型的递归方法时,F# 需要帮助。一个更愉快的选择是注释B.GetInstance的定义:

    type A() =
      member x.Call() = B.GetInstance().Call()
    
    and B() =
      static member GetInstance() : B = new B()
      member x.Call() = ()
    

    我相信你遇到这个问题的原因是 F# 试图同时解决 A 和 B 中所有方法上的所有推断类型(因为它们被定义为相互递归的类型),这会导致问题,但也许有人F# 团队的成员将参与进来。

    【讨论】:

    • 这不直观理解。拯救了我的一天,谢谢!
    【解决方案2】:

    快速总结是,在递归组中(例如,一种类型的成员,或者像我们这里的递归类型的成员)F# 以从左到右的方式读取 声明底部顺序,然后是从左到右从上到下的定义。所以在这种情况下,当它到达A.Call 的定义时,它还没有读取B.GetInstance定义,因此(还!)不知道GetInstance 的返回类型将是B

    Keith 的答案针对这种情况,您可以提供类型注释以在其声明中指定 GetInstance 的返回类型。

    Forcing F# type inference on generics and interfaces to stay loose

    深入讨论这里发生的事情。

    还请注意,在您最初的尝试中,您不需要“强制转换”(潜在的动态操作,使用 :>),而只需“注释”(静态声明类型,使用 :)让它编译。但是将类型注释放在GetInstance 的方法声明中更有意义(通常,更喜欢在方法签名上添加注释,而不是在主体内的任意位置)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-05
      • 2012-10-19
      相关资源
      最近更新 更多