我想实现一个读取字符串并对其执行数学运算的程序。
addop, mulop :: Parser (Expr -> Expr -> Expr)
addop = (infixOp "+" Add) <|> (infixOp "-" Sub)
mulop = infixOp "*" Mul
int :: Parser Expr
int = do
n <- number
return (Lit n)
expr :: Parser Expr
expr = term `chainl1` addop
term :: Parser Expr
term = factor `chainl1` mulop
factor :: Parser Expr
factor = int <|> parens expr
run :: String -> Expr
run = runParser expr
eval :: Expr -> Int
eval ex = case ex of
Add a b -> eval a + eval b
Mul a b -> eval a * eval b
Sub a b -> eval a - eval b
Lit n -> n
evExpr :: String -> Maybe Integer
evExpr [] = Nothing
evExpr str = Just (eval (run str))
但我有错误:
• Couldn't match type ‘Int’ with ‘Integer’
Expected type: Maybe Integer
Actual type: Maybe Int
• In the expression: Just (eval (run str))
In an equation for ‘evExpr’: evExpr str = Just (eval (run str))
|
37 | evExpr str = Just (eval (run str))
| ^^^^^^^^^^^^^^^^^^^^^
和
• Couldn't match type ‘SourceName
-> [Char] -> Either ParseError Expr’
with ‘Expr’
Expected type: String -> Expr
Actual type: () -> SourceName -> [Char] -> Either ParseError Expr
• Probable cause: ‘runParser’ is applied to too few arguments
In the expression: runParser expr
In an equation for ‘run’: run = runParser expr
|
26 | run = runParser expr
| ^^^^^^^^^^^^^^
当程序正常运行时,我应该看到这样:
•evExpr“27-(6 * 3 + 5%2)”=只是8
请帮帮我。谢谢
答案 0 :(得分:5)
函数eval
会返回Int
,但在evExpr
中,您试图将Int
推送到Maybe Integer
(基于类型签名) evExpr
)。 Int
不是Integer
,因此您会收到错误消息。您可以更改eval
以返回Integer
,更改evExpr
以返回Maybe Int
,或将Int
转换为Integer
{ {1}}。
发生第二个错误,因为fromIntegral
具有类型签名:
runParser
但是您使用runParser :: GenParser tok st a -> st -> SourceName -> [tok] -> Either ParseError a
和Parser Expr
来调用它,并遗漏了String
和SourceName
个参数。
我猜你的解析器没有任何用户状态,所以你可以使用:
st
哪个不需要用户状态(因为它具有类型parse :: Stream s Identity t => Parsec s () a -> SourceName -> s -> Either ParseError a
),但仍需要您传递源的名称。类似的东西:
()
您遇到的下一个问题是run :: String -> Either ParseError Expr
run = parse expr "<string>"
如果解析器遇到解析错误,则无法返回run
。解析器返回Expr
,您必须在Either ParserError Expr
中处理该问题。实际上,检查evExpr
中的空列表/ String
没有意义,因为解析器将处理它(并生成错误)。您最好更改evExpr
以返回evExpr
,并Either ParseError Int
fmap
超过解析器结果。
eval