尽管其他地方正在处理数据处理,但函数错误中的非详尽模式



我正在尝试编写一种简单的语言,目前我正在尝试实现一个循环,但每次运行程序时,我都会收到一个错误,即evalStatement_函数中存在一个非穷举模式。

----- Main -----
readStatement :: String -> IO [HStatement]
readStatement input = do
program <- readFile input
case parse parseProgram "Olivia" program of
Left err -> fail $ show err
Right parsed -> return $ parsed

evalString :: Env -> String -> IO String
evalString env expr = do
x <- readStatement expr
concat <$> mapM (runIOThrows . liftM show . evalStatement_ env) x
--mapM (runIOThrows . liftM show . evalStatement env) x
-- evalStatement env x
--map (exprs -> runIOThrows $ liftM show $ evalStatement env exprs) x
--map (runIOThrows $ liftM show $ evalStatement env) x
--runIOThrows $ liftM show $ (evalStatement env x)   -- >>= runIOThrows $ liftM show $ evalStatement env
evalAndPrint :: Env -> String -> IO ()
evalAndPrint env expr = do
evalString env expr
return ()
run :: String -> IO ()
run expr = nullEnv >>= flip evalAndPrint expr
main :: IO ()
main = do
args   <- getArgs
run $ args !! 0
----- Error -----
Main: Expr.hs:(82,1)-(85,34): Non-exhaustive patterns in function evalStatement_
-----------------
evalStatement_ :: Env -> HStatement -> IOThrowsError ()
evalStatement_ env (Do cond expr) = evalDo env (Do cond expr)
evalStatement_ env (Print val) = do
x <- evalVal env val
liftIO $ putStrLn $ show x 
evalDo :: Env -> HStatement -> IOThrowsError ()
evalDo env (Do cond expr) = evalVal env cond >>= x -> case x of
HBool False -> return ()
HBool True  -> do
traverse_ (evalVal env) expr
evalStatement_ env $ Do cond expr
evalVal :: Env -> HVal -> IOThrowsError HVal
evalVal env val @(HInteger _) = return $ val
evalVal env val @(HBool    _) = return $ val
evalVal env val @(HString  _) = return $ val
evalVal env val @(HList    _) = return $ val
evalVal env (Arith x op y)    = evalArithmetic env x op y
evalVal env (Assign var val)  = evalVal env val >>= defineVar env var

我将错误归结为这些函数。我使用evalStatement_来评估DoPrint函数。我已经测试了print,它确实有效,但我不明白为什么evalDo不起作用。evalVal按预期工作,所以我不知道非详尽的问题在哪里。我使用-Wall -Wextra运行了compile命令,它根据Statement数据类型为我提供了以下内容。

Expr.hs:82:1: warning: [-Wincomplete-patterns]
Pattern match(es) are non-exhaustive
In an equation for ‘evalStatement_’:
Patterns not matched:
_ (Eval _)
_ (Program _)
|
82 | evalStatement_ env (Do cond expr) = evalDo env (Do cond expr)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
data HStatement
=  Eval   HVal
|  Print  HVal
|  Do     HVal [HVal]
|  Program [HVal]
deriving (Eq, Read)

我不知道为什么EvalProgram会影响到实际上没有使用它们的东西,或者我完全错过了什么?

您的main程序在从源文件解析的语句的完整列表上按顺序运行evalStatement_

evalString :: Env -> String -> IO String
evalString env expr = do
x <- readStatement expr
concat <$> mapM (runIOThrows . liftM show . evalStatement_ env) x 
^^^^ runs on every statement in the list `x`

如果语句列表x :: [HStatement]包含任何ProgramEval语句,那么这将导致运行时错误,因为evalStatement_只处理DoPrint构造函数。

因此,正如@jpmarinier所评论的,如果您希望对任何有效的语句调用evalStatement_,那么您需要处理编译器在打开-Wall时警告您的所有情况。

以下缺失案例的定义可能适用于您使事情正常运行:

evalStatement_ env (Program pgm) = mapM_ (evalStatement_ env) pgm
evalStatement_ env (Eval val) = do
result <- evalVal env val
return ()

请注意,Eval的情况非常无用。由于evalStatement_不能返回除()之外的任何其他内容,因此我们最终会计算一个结果,然后将其丢弃。这将几乎和刚刚做的一样:

evalStatement_ _ (Eval _) = return ()  -- do nothing

最新更新