繁体   English   中英

为什么使用Maybe时catch不能正确调用处理程序?

[英]Why does catch not properly invoke handler when using Maybe?

考虑以下 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))

我打算让这段代码工作的方式是评估表达式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

)

但是,我认为懒惰的评估正在阻止这种情况发生。 当我在 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" ""

而不是一个漂亮的印刷错误。

对我来说,似乎代码没有按照我的意图工作,因为由于延迟评估,系统仅在它已经开始形成父表达式Just x后才实际计算表达式evaluate $ lex_rgx rgx_str

我是否正确,如果正确,是否有任何优雅的方法来规避这个问题?

evaluate仅将值评估为 WHNF(即匹配(:)[] ,但不能进一步匹配),但您的错误隐藏在列表的元素内。 以下函数强制列表的所有元素(或使用 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

然而,在元素中隐藏异常首先是一种有问题的方法,请考虑重构词法分析器以不使用异常,产生一个信息丰富的Either中继所有可能的错误,而不是使用Maybe它的Just甚至不能保证成功解析。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM