无法将预期类型“整数”与推断类型“值”匹配

时间:2011-09-13 11:41:58

标签: haskell

我正在尝试在Haskell中实现以下代码,以评估算术表达式,遗憾的是它在Couldn't match expected type `Integer' against inferred type `Value'处给出了错误(IVal (eval c x)) + (IVal (eval c (Prim IntAddOp xs)))). Plz帮我解决了一些问题。

     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))))

谢谢...

3 个答案:

答案 0 :(得分: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。

答案 1 :(得分:2)

此错误意味着它所说的内容。

首先,Haskell期待什么?

IVal ( something )

Haskell希望something成为Integer,因为您对Value的定义应该是:

data Value
     = IVal Integer
     | BVal Bool

其次,Haskell推断了什么?

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

我必须假设您为Num定义了Value个实例,否则+将无效。因此,当您向Value添加Value时,您应该获得Value结果。 (我知道添加的两件事是Values,因为IValValue类型的构造函数)

所以Haskell推断这个表达式的类型为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

在这里,我使用了将布尔值视为1或0的可怕的类似C的约定。您可能希望在extract s上保留BVal未定义,或者抛出错误,或其他任何内容。至少现在我们有办法从Integer中提取Value

所以现在我假设你实际上没有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)))

问题解决了吗?

答案 2 :(得分: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 = ...;

谢谢你们帮助人们.......