F#奇怪的类型错误信息

时间:2015-06-06 19:45:35

标签: types f# typeerror discriminated-union

任何人都可以告诉我F#中的以下错误消息含义:

Program.fs(1021,16): error FS0001: This expression was expected to have type
    FSI_0051.ExprTree
but here has type
    FSI_0061.ExprTree

这是执行以下功能的结果:

let evaluate_tree tree =
    let rec helper tree =
        match tree with
        | Value(x) -> Value(x)
        | Node(l, op, r) -> evaluate (helper l) op (helper r)
    get_float (helper tree)

第1021行是上述函数的最后一行。另外,我在evaluate_tree

之前声明了以下函数和类型
type Operator =
    | Plus
    | Minus
    | Mult
    | Divide

type ExprTree =
    | Value of float
    | Node of ExprTree * Operator * ExprTree
    static member (-) (a, b) =
        match (a, b) with
        | (Value(x), Value(y)) -> Value(x - y)
    static member (+) (a, b) =
        match (a, b) with
        | (Value(x), Value(y)) -> Value(x + y)
    static member (/) (a, b) =
        match (a, b) with
        | (Value(x), Value(y)) -> Value(x/y)
    static member (*) (a, b) =
        match (a, b) with
        | (Value(x), Value(y)) -> Value(x*y)

请注意,在下面的函数中,当我没有添加显示Node(_,_,_) -> 0.0(注释)的行时,它给出了上述错误消息。但是,当我添加该行时,错误消息消失了(我仍然想知道错误消息的含义):

let get_float value =
    match value with
    | Value(x) -> x
    //| Node(_, _, _) -> 0.0

let evaluate (value1 : ExprTree) operator (value2 : ExprTree) =
    match operator with
    | Plus -> value1 + value2
    | Minus -> value1 - value2
    | Mult -> value1*value2
    | Divide -> value1/value2

let evaluate_tree tree =
    let rec helper tree =
        match tree with
        | Value(x) -> Value(x)
        | Node(l, op, r) -> evaluate (helper l) op (helper r)
    get_float (helper tree)

进一步说明:evaluate_tree评估表达式树。表达式树包含ExprTree: Value and Node中定义的类型。我认为这可能与我没有在get_float中提供Node(我最终考虑)的情况有关。但是,get_float永远不会评估Node,而不是我使用它的方式,除非树是错误的(即它将操作符作为叶节点)。

提前致谢!

1 个答案:

答案 0 :(得分:4)

您的错误是由在FSI中执行的每个评估实际创建动态程序集FSI_XXXX的事实引起的。实际上,您使用ExprTree定义的函数可能是指FSI_0051.ExprTree,而您稍后定义并使用ExprTree的函数现在指的是FSI_0061.ExprTree

我通常采取的措施是修复错误,只需再次使用ExprTree执行我所有函数的定义,现在有一个较新的FSI_0061.ExprTree并且所有函数都可以正常工作。

您只需要注意,每个具有相同名称的新评估都将 shadow 预先存在的符号。另一方面,它们仍然是不同的符号,因此有两个名称FSI_0051.ExprTreeFSI_0061.ExprTree