Haskell: Почему моя функция оценки арифметики c не выполняется, пока выполняется оценка данных? - PullRequest
0 голосов
/ 08 мая 2020

Я пишу на простом языке, но столкнулся с проблемой в том, что арифметические выражения c не ожидают своих операторов, несмотря на то, что они определены в языке. С тех пор я вернулся к express своей программе, более простой. На данный момент единственное сложное выражение, которое у меня есть, это арифмети c. Я могу разбирать целые числа, строки, логические значения и списки. Он может распознавать такие выражения, как «5 Добавить 5», но только в форме списка «[5 Добавить 5]».

Я подозреваю, что он не анализирует, когда его нет в списке, из-за того, как анализируются атомы. Парсер атома разбирает логические, а затем произвольный атом. Если выражение arithmeti c помещается в строку, оно также будет правильно проанализировано.

Я не уверен, почему он не оценивается правильно. У меня есть функция оценки, которая имеет дело с выражениями arithmeti c, но она не работает, когда я пытаюсь передать ей аргументы через командную строку. Когда я загружаю его в GHCI, я могу использовать его отлично, поэтому я знаю, что функция оценки arithmeti c работает, но я не понимаю, почему она не выполняет оценку, когда я даю ей аргументы командной строки. Любое выражение arithmeti c дает только само выражение, а не значение, которое должно быть возвращено.

Единственная причина, по которой я могу думать, это то, что когда выражение анализируется, оно не анализируется как выражение c arithmeti, а вместо этого анализируется как список или строка.

data HenryVal = Integer Integer
              | Bool Bool
              | Atom String
              | String String 
              | List [HenryVal]
              | ABinOp ABinOp
              | Ad HenryVal HenryVal
              | ABinary ABinOp HenryVal HenryVal

data ABinOp = Add
            | Subtract
            | Multiply
            | Divide
             deriving (Show)

evalABinOp :: HenryVal -> ABinOp -> HenryVal -> HenryVal
evalABinOp (Integer a) Add (Integer b) = Integer (a +b)
evalABinOp (Integer a) Multiply (Integer b) = Integer (a * b)
evalABinOp (Integer a) Divide (Integer b) = Integer (a `div` b)
evalABinOp (Integer a) Subtract (Integer b) = Integer (a - b) 

eval :: HenryVal -> HenryVal
eval val@(Atom _) = val
eval val@(String _) = val
eval val@(Integer _) = val
eval val@(Bool _) = val
eval (List [Atom "quote", val]) = val
eval val@(List _) = val
eval (ABinary op x y) = evalABinOp (eval x) op (eval y)

spaces :: Parser ()
spaces = skipMany1 space

parseString :: Parser HenryVal
parseString = do
    char '"'
    x <- many (noneOf "\"")
    char '"'
    return $ String x

parseList :: Parser HenryVal
parseList = liftM List $ sepBy parseExpr spaces

parseNumber :: Parser HenryVal
parseNumber = liftM (Integer . read) $ many1 digit

parseAtom :: Parser HenryVal
parseAtom = do 
              first <- letter
              rest <- many (letter <|> digit)
              let atom = first:rest
              return $ case atom of 
                         "True" -> Bool True
                         "False" -> Bool False
                         _ -> Atom atom

parseExpr :: Parser HenryVal   
parseExpr =  parseNumber <|>
             parseAtom   <|>
             parseString <|>
             do
                 _ <- char '['
                 x <- try parseList
                 _ <- char ']'
                 return x

readExpr :: String -> HenryVal
readExpr input = case parse parseExpr "Henry" input of
    Left error -> String $ "No Match: " ++ show error
    Right val -> val

main :: IO ()
main = getArgs >>= print . eval . readExpr . head
...