2011-10-26 38 views
5

我有一個簡短的問題。哈斯克爾扔我的57 - Undefined variable "f" error,我不知道爲什麼。如果你能看看這個,我會很感激。未定義的變量,Haskell

代碼:

eval :: Expr -> Environment -> Float 
eval expr env = eval' expr 
    where 
    eval' :: Expr-> Float 
    eval' (Num num) = num 
    eval' (App app exprs) = foldl1 (f) (map eval' exprs) -- **Line 57** 
    eval' (Id id) = 5 
     where 
     f = getFunctionForApp app     -- **f is here** 
     getFunctionForApp :: String -> (Float->Float->Float) 
     getFunctionForApp "+" = (+) 
     getFunctionForApp "-" = (-) 
     getFunctionForApp "*" = (*) 
     getFunctionForApp "/" = (/) 
     getIdVal :: String -> Environment -> Float 
     getIdVal id ((curId, val):envrs) 
      |curId == id = val 
      | otherwise = getIdVal id envrs 

類型定義:

data Expr = Num Float | Id String | App String [ Expr ] 
      deriving (Eq, Ord, Show) 
type Environment = [ (String, Float) ] 
+3

我誠實地不知道答案,但我認爲在發表聲明後必須提到where塊。換句話說,你是否嘗試過移動整個阻塞一條線? – Ramy

回答

9

的地方塊僅適用於案前將其直接,不給eval'功能的所有案件。因此,feval' (Id id) = 5中定義(但未使用),但它不在第57行的範圍內。要解決此問題,您需要直接在第57行後移動where區塊。

+0

或者直接在最後一個「eval」行之後放上「f = ...」 - 將where塊嵌入另一個塊中,其中塊對我來說似乎很陌生,但也許在某些情況下有很好的理由。 – MatrixFrog

+0

@MatrixFrog:是的,有時候有很好的理由來嵌套'where';例如,如果您手動應用「靜態參數轉換」。在這裏,嵌套的'where'用於爲使用模式中綁定的值創建一個短名稱,這也是一種常見用法。 –

3

究竟是sepp2k說的。不過,在這種情況下,我寧願簡單地交換第57行和第58行,以便where附加在正確的等式上,而不用拆分eval'的等式,這樣更具可讀性。

或者不使用f可言,使其

eval' (App app exprs) = foldl1 (getFunctionOrApp app) (map eval' exprs) 
eval' (Id id) = 5 

getFunctionOrApp :: String -> (Float -> Float -> Float) 
getFunctionOrApp "+" = ... 

移動getFunctionOrApp(和getIdVal)到同一級別whereeval',它甚至可能是合理的頂層定義它們。