我正在尝试为布尔表达式编写一个求值程序。这里的evalAExp :: AExp->类型;也许Int(即算术表达式评估器)。算术评估员正在为我工作。
在布尔评估器中我希望类型为:: BExp - >布尔。
在编译时,我收到类似Couldn't match expected type ``Bool' with actual type ``BExp'
In the pattern: Eq a1 a2
In an equation for ``evalBExp':
evalBExp (Eq a1 a2) = evalAExp (a1) == evalAExp (a2)
BExp的结束类型应该是Bool。
在这种情况下,我应该如何声明我的BExp。是否有更好的方法来实现它。
data BExp = Eq AExp AExp | Lt AExp AExp | Gt AExp AExp | ELt AExp AExp| EGt AExp AExp | And BExp BExp | Or BExp BExp | Bool
evalBExp True = True
evalBExp False = False
evalBExp (Eq a1 a2) = evalAExp (a1) == evalAExp (a2)
这里在evalBExp (Eq a1 a2) = evalAExp (a1) == evalAExp (a2)
我正在比较Just Int == Just Int,结果是Bool。我该怎么办?我认为数据BExp声明本身存在问题。
任何帮助
编辑:
我将代码改为这样的代码。
data BExp = Eq AExp AExp | Lt AExp AExp | Gt AExp AExp | ELt AExp AExp| EGt AExp AExp | And BExp BExp | Or BExp BExp |Boolean Bool
evalBExp (Boolean True) = True
evalBExp (Boolean False) = False
evalBExp (Eq a1 a2) = (evalAExp (a1)) == (evalAExp (a2))
所以我将类型更改为布尔Bool。这是一种声明类型的更好方法吗?为什么不像以前那样只是Bool。有没有更好的方法来做到这一点。
整个代码
import qualified Data.Map as M
import Data.List
data AExp = Var Char | Value Int | Add AExp AExp | Mul AExp AExp | Sub AExp AExp
data BExp = Eq AExp AExp | Lt AExp AExp | Gt AExp AExp | ELt AExp AExp| EGt AExp AExp | And BExp BExp | Or BExp BExp |Boolean Bool
data AssignExp = AExp Char | BExp Char
data Statement = AssignExp | While BExp Statement
type Env = M.Map Char Int
env = M.fromList[('A',1),('B',2),('C',3)]
evalAExp :: AExp -> Maybe Int
evalAExp (Value x) = (Just x)
evalAExp (Var x) = M.lookup x env
evalAExp (Add a1 a2) =do
v2<-evalAExp a2;v1<-evalAExp a1
return (v1+v2)
evalAExp (Sub a1 a2) =do
v2<-evalAExp a2;v1<-evalAExp a1
return (v1-v2)
evalAExp (Mul a1 a2) = do
v1 <-evalAExp a1;v2 <- evalAExp a2
return (v1*v2)
evalBExp (Boolean True) = True
evalBExp (Boolean False) = False
evalBExp (Eq a1 a2) = (evalAExp (a1)) == (evalAExp (a2))
答案 0 :(得分:7)
您的怀疑,&#34;我认为数据BExp声明本身存在问题&#34;,是正确的。你所写的并不代表我怀疑你希望它做的事情。错误发生在最右端(因为错误经常发生)所以我不得不滚动才能找到它。使用更多的垂直空间,让我们看看。
data BExp
= Eq AExp AExp
| Lt AExp AExp
| Gt AExp AExp
| ELt AExp AExp
| EGt AExp AExp
| And BExp BExp
| Or BExp BExp
| Bool
这是最后一个大问题。它更难发现,因为虽然你告诉我们,&#34;我希望类型是:: BExp - &gt; Bool&#34;,你不告诉编译器。如果您已经做了体面的事情并通过编写显式类型签名来传达您的意图,那么错误报告可能会更有帮助。你的课程开始
evalBExp True = True
这足以说服typechecker预期的类型是
evalBExp :: Bool -> Bool
因为True :: Bool
。当第3行显示
evalBExp (Eq a1 a2) = evalAExp (a1) == evalAExp (a2)
突然想知道为什么你要evalBExp
BExp
而不是Bool
。
现在,我怀疑你的印象是BExp
| Bool
制作True :: BExp
和False :: BExp
,但这根本不是它的作用。相反,您将发现您有一个无效的数据构造函数Bool :: BExp
,其名称与数据类型Bool
一致但位于完全独立的命名空间中。我相信你的意图是将Bool
的值静静地嵌入BExp
,但是Haskell不允许这种微妙的子类型。要达到预期的效果,您需要一个显式打包Bool
的构造函数,所以请尝试
data BExp
= ...
| BVal Bool
和
evalBExp :: BExp -> Bool
evalBExp (BVal b) = b
...
更接近你的计划。
您当然可以为Bool
构造函数使用名称BVal
,因此请写
data BExp
= ...
| Bool Bool
其中第一个Bool
是数据构造函数,第二个是类型构造函数,但我觉得这个选择令人困惑。