2011-09-13 64 views
1

我試圖在Haskell中實現以下代碼,以評估算術表達式,不幸的是它給了我錯誤Couldn't match expected type `Integer' against inferred type `Value'(IVal (eval c x)) + (IVal (eval c (Prim IntAddOp xs)))). Plz幫助我一些解。無法匹配期望的類型'Integer'對推斷類型'值'

 type Env = GenEnv Value 

    data Value 
     = IVal Integer 
     | BVal Bool 

    -------------------------------------------------- 
    eval :: Env -> Exp -> Value 
    eval _ (Num n) = IVal n 
    eval _ (Prim IntAddOp ((Num x) : (Num y):[])) = IVal (x+y) 
    eval c (Prim IntAddOp (x: xs)) = IVal ((IVal (eval c x)) + (IVal (eval c 
             (Prim IntAddOp xs)))) 

謝謝...

回答

4

最後一行應改爲:

IVal $ 
    case eval c x of 
    IVal ix -> 
     case eval c (Prim IntAddOp xs) of 
     IVal ip -> ix + ip 
     _  -> error "trying to add int value to bool value" 
    _  -> error "trying to add bool value to int value" 

(或類似你沒有提供的數據結構的所有定義,以確保東西。 。)

然而,這可以多一些收拾。此外,你似乎從來沒有使用Env參數。

編輯:這是一個更好的做法。注意我們正在使用Maybe monad:將一個布爾值添加到整數值是沒有意義的。

eval :: Expression -> Maybe Value 
eval (Integer i) = return $ IVal i 
eval (Boolean b) = return $ BVal b 
eval (Add l r) = 
    do el <- eval l 
    er <- eval r 
    return . IVal $ l + r 
eval (And l r) = 
    do el <- eval l 
    er <- eval r 
    return . BVal $ l && r 
... and so on 

如果您想要錯誤消息,請將Maybe與錯誤monad替換。

2

這個錯誤的含義正是它所說的。

首先,什麼沒想到哈斯克爾?

IVal (something) 

哈斯克爾預計something是一個Integer,因爲你的Value定義說應該是:所有的

data Value 
    = IVal Integer 
    | BVal Bool 

二,什麼也Haskell的推斷?

(IVal (eval c x)) + (IVal (eval c (Prim IntAddOp xs))) 

我必須假設您已經定義了一個Num實例Value S,否則+是行不通的。因此,當您將Value添加到Value時,您應該得到Value結果。 (我知道要添加的兩件事情是因爲ValuesIVal一個構造函數Value型)

所以哈斯克爾推斷,這個表達式類型Value

他們爲什麼不匹配?

Haskell期待Integer表達式,並且您給它一個Value表達式。這個錯誤的含義正是它所說的。那麼如何解決它?那麼,我不知道。在黑暗中刺中,您可以從添加中刪除IVal構造函數。

((eval c x) + (eval c (Prim IntAddOp xs))) 

等一下,的eval結果是Value,而不是一個Integer,所以......我們仍在增加Values,並在IVal包裝這些更是錯誤的比以前。

我們如何定義一個函數來獲取Integer中的一個IVal

extract :: Value -> Integer 
extract (IVal x) = x 
extract (BVal True) = 1 
extract (BVal False) = 0 

這裏我使用治療布爾駭人聽聞的類C約定的1或0。你可能要離開extract未定義的BVal S,或拋出一個錯誤,或者別的什麼東西。至少現在我們有一種方法可以從Value中提取Integer

所以現在我假設你實際上不要有一個Num實例爲Value。我們只需從這兩個表達式中提取Integers以將它們添加在一起。

(extract (eval c x) + extract (eval c (Prim IntAddOp xs))) 

現在應該被推斷爲一個Integer。那麼我們可以把它包裝在一個IVal構造函數中。

IVal (extract (eval c x) + extract (eval c (Prim IntAddOp xs))) 

問題解決了嗎?

0
eval _ (Prim _ ([])) = IVal (0) 

eval _ (Prim IntAddOp ((Num x) : (Num y):[])) = IVal (x+y) 
eval s (Prim IntAddOp (x: xs)) = IVal (test (eval s x)+ test (eval s (Prim IntAddOp 
    xs))) 

這工作正常,它正在評估1 + 2 + 3 = ...;

謝謝你幫助傢伙.......

相關問題