1 haskell exception lazy-evaluation catch-block
考虑以下 Haskell 代码
try_lex_rgx :: String -> IO (Maybe [RgxToken])
try_lex_rgx rgx_str =
catch
(do
rgx_toks <- evaluate $ lex_rgx rgx_str
return $ Just rgx_toks)
(\(LexerErr err_msg remainder) -> disp_lex_error rgx_str (LexerErr err_msg remainder))
Run Code Online (Sandbox Code Playgroud)
我打算让这段代码工作的方式是评估表达式lex_rgx rgx_str,在它们发生时捕获任何异常,然后调用disp_lex_error以漂亮地打印错误。
(顺便说一下,disp_lex_error的代码如下
disp_lex_error :: String -> RgxLexerException -> IO (Maybe [RgxToken])
disp_lex_error rgx_str (LexerErr err_msg remainder) = let loc_str_frag = "In regex " ++ rgx_str ++ " at ..." in
do
hPutStrLn stderr ("Lexer error: " ++ err_msg ++ "\n" ++
loc_str_frag ++ remainder ++ "\n" ++
(replicate (length loc_str_frag - 1) ' ') ++ "^^")
evaluate Nothing
Run Code Online (Sandbox Code Playgroud)
)
但是,我认为懒惰的评估正在阻止这种情况发生。当我在 ghci 中使用调用错误的输入运行代码时,我收到以下消息
*Rgx.RgxLexer> :l Rgx.RgxLexer
[1 of 2] Compiling Rgx.RgxTok ( Rgx/RgxTok.hs, interpreted )
[2 of 2] Compiling Rgx.RgxLexer ( Rgx/RgxLexer.hs, interpreted )
Ok, two modules loaded.
*Rgx.RgxLexer> try_lex_rgx "\\"
Just [*** Exception: LexerErr "Dangling \"\\\" is not allowed" ""
Run Code Online (Sandbox Code Playgroud)
而不是一个漂亮的印刷错误。
对我来说,似乎代码没有按照我的意图工作,因为由于延迟评估,系统仅在表达式evaluate $ lex_rgx rgx_str
已经开始形成父表达式后才实际计算表达式Just x。
我是否正确,如果正确,是否有任何优雅的方法来规避这个问题?
evaluate仅将值计算为 WHNF(即匹配(:)or [],但不能进一步匹配),但您的错误隐藏在列表元素内。以下函数强制列表的所有元素(或使用 deepseq 库以获得更通用的接口)。
-- Evaluates each element to WHNF (which might not be enough for all use cases)
evaluateList :: [a] -> IO [a]
evaluateList xs = evaluate (foldr seq () xs) >> pure xs
Run Code Online (Sandbox Code Playgroud)
然而,在元素隐藏例外情况是有问题的方法,首先,考虑重构词法分析器不使用异常,产生一个信息Either是继电器的所有可能的错误,而不是使用Maybe它Just甚至不保证一次成功的解析。
| 归档时间: |
|
| 查看次数: |
53 次 |
| 最近记录: |