评估操作字符串,但代码不起作用

时间:2019-03-25 03:35:05

标签: haskell

我需要编写一个代码,该代码评估操作字符串并输出该字符串的结果整数。我写了一些东西,但是没用,需要一些帮助。我需要使用折叠,因为它比较容易,但是我确定出了什么问题。这是在Haskell上,并使用Emacs。

evalExpr :: String -> Int
evalExpr xs = foldl 0 xs where
  f v x | x == "+" = (+) v
        | x == "-" = (-) v
        | x == " " = 0
        | otherwise = read v :: Int

例如:

evalExpr“ 2 + 4 + 5-8”

输出应为:3

evalExpr“”

输出应为:0

这是因为它应该从左到右读取字符串。

2 个答案:

答案 0 :(得分:1)

您可以按照@ 5ndG的建议进行操作。但是,要评估操作字符串,使用parsec是更好的方法。这是您的情况的示例:

module EvalExpr where

-- You need parsec to do parsing work, and the following are just example 
-- modes for your simple case.
import Text.Parsec
import Text.Parsec.Char
import Text.Parsec.String

-- A data structure for your simple arithmetic expresssion
data Expr = Lit Int
          | Plus Expr Expr
          | Minus Expr Expr
          deriving Show

-- Evaluate an Expr to an integer number
eval :: Expr -> Int
eval (Lit n) = n
eval (Plus e1 e2) = eval e1 + eval e2
eval (Minus e1 e2) = eval e1 - eval e2

-- The following do the parsing work
-- Parser for an integer number
int :: Parser Expr
int = Lit . read <$> (many1 digit <* spaces)      -- A number may be followed by spaces

-- Parser for operators "Plus" and "Minus"
plus, minus :: Parser (Expr -> Expr -> Expr)
plus = Plus <$ char '+' <* spaces
minus = Minus <$ char '-' <* spaces

-- Parser for Expr
expr :: Parser Expr
expr = chainl int (plus <|> minus) (Lit 0)

-- Evalute string to an integer
evalExpr :: String -> Int
evalExpr s = case parse expr "" s of
               Left err -> error $ show err
               Right e  -> eval e

以上只是使用parsec的简单示例。如果您的实际情况比较复杂,则需要做更多的工作。因此,学习使用parsec是必要的。 intro_to_parsing是一个好的开始。 package description中也有一些学习资源。

顺便说一下,Text.Parsec.Expr中的parsec可以更方便地解析表达式,但是最重要的是,您需要了解parsec的基本知识。

学习愉快!

答案 1 :(得分:0)

与您的示例相距不远。试试这个:

evalExpr :: String -> Int
evalExpr xs = foldl f (0 +) xs 0

f :: (Int -> Int) -> Char -> (Int -> Int)
f v ch | ch == '+' = (v 0 +)
       | ch == '-' = (v 0 -)
       | ch == ' ' = v
       | otherwise = (v (read [ch] :: Int) +)

所以与您的主要区别在于,折数中的累加器是一个可以吸收一个Int并产生一个Int的函数,而不仅仅是一个Int。