2015-06-06 216 views
2

誰能告訴我什麼是以下錯誤消息在F#是指:F#奇怪類型的錯誤消息

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

這是執行以下功能的結果是:1021

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前:

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,而不是以我使用它的方式進行評估,除非樹錯了(即它將有一個運算符作爲葉節點)。

在此先感謝!

+3

我認爲這個錯誤信息意味着在F#交互中,在交互式會話中早期評估的ExprTree類型的兩個版本之間存在衝突。嘗試重置交互式會話並重新評估腳本中的所有值 – Petr

回答

4

您的錯誤是由FSI中執行的每個評估實際創建一個動態組件FSI_XXXX引起的。因此,實際上,您用ExprTree定義的函數可能是指FSI_0051.ExprTree,而您稍後定義並使用ExprTree的函數現在指的是FSI_0061.ExprTree

我通常會修正錯誤,只是再次使用ExprTree執行我所有函數的定義,現在有一個更新的FSI_0061.ExprTree,並且所有函數都應該可以工作。

您只需要注意,每個具有相同名稱的新評估將預先存在符號影子。另一方面,它們仍然是不同的符號,因此兩個名稱FSI_0051.ExprTreeFSI_0061.ExprTree

+0

對於遲到的回覆很抱歉。所以你的意思是我第一次執行'ExprTree'的**定義**時,它創建了'FSI_0051.ExprTree',第二次'FSI_0061.ExprTree'?然後,錯誤顯然出現了,因爲我在定義第二個函數和變量之前定義了一些函數和變量,而在定義第二個函數和變量之後定義了一些。那麼我在第二個之後定義的那個預期'FSI_0061.ExprTree',但其他變量/函數仍然在'FSI_0051.ExprTree'上運行? –

+1

雅差不多。基本上,類型名稱在定義評估時被解析。所以除非你是通用的,否則使用「舊」類型。 –