2011-09-13 12 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 'と推測型` Value'を一致させることができませんでした

 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モナドでは、整数値にブール値を追加することは意味がありません。

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 

エラーメッセージが必要な場合は、エラーモナドに置き換えてください。

2

このエラーは、それが何を言っているかを正確に意味しています。

まず、ハスケルは何を期待しましたか?

IVal (something) 

HaskellはValueのあなたの定義は、それがあるべきと言ったので、somethingIntegerことを期待:すべての

data Value 
    = IVal Integer 
    | BVal Bool 

第二に、Haskellは何を推測するのですか?

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

私はあなたがそうでなければ+が動作しない、Value秒間Numインスタンスを定義したと仮定しなければなりません。したがって、ValueValueに追加すると、結果はValueになるはずです。だから、Haskellは、この式はタイプValueを持っていることを推測

(私はIValValue型のコンストラクタであるため、追加されている2つのものがValuesであることを知っています)。

なぜ一致しませんか?

ハスケルはIntegerという表現を期待しており、それにValueという表現を付けました。エラーは、それが言うことを正確に意味します。どのようにそれを修正するには?まあ、私はヒントはありません。暗闇の中で刺すと、追加からコンストラクタIValを削除することができます。

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

ちょっと待っては、evalの結果はValue、ないIntegerので、...我々はまだValuesを追加し、IValでこれらをラッピングしていると、それは以前よりもさらに多くの間違っています。

IValのうちIntegerを取得する関数を定義することはどうでしょうか。私はあなたがBValの上で未定義のextractを残す、またはエラー、または何をスローする場合があります1または0として処理するブール値の恐ろしいC-のような規則を使用しています。ここ

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

。少なくとも今、ValueからIntegerを抽出する方法があります。

だから今、私はあなたが実際にValueためNumインスタンスを持っていないと仮定しています。それら2つの式を一緒に追加するために、その2つの式のうち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 = ...を評価しても問題なく動作します。

お手数をおかけします.......

関連する問題