我正在尝试编写一种简单的语言,目前我正在尝试实现一个循环,但每次运行程序时,我都会收到一个错误,即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_
来评估Do
和Print
函数。我已经测试了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)
我不知道为什么Eval
和Program
会影响到实际上没有使用它们的东西,或者我完全错过了什么?
您的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]
包含任何Program
或Eval
语句,那么这将导致运行时错误,因为evalStatement_
只处理Do
和Print
构造函数。
因此,正如@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