也许MonadPlus解析器需要在一定的顺序



我正在完成wikibooks/haskell上的练习,monadplus章节中有一个练习,希望您编写这个hexChar函数。我的函数的工作方式如下所示,但问题是,当我尝试切换2个helper解析器(digitParse和alphaParse)时,函数就不能正常工作了。如果我把它们调换一下,我就只能解析数字而不能解析字母字符了。

为什么会这样?

char :: Char -> String -> Maybe (Char, String)
char c s = do
    let (c':s') = s
    if c == c' then Just (c, s') else Nothing
digit :: Int -> String -> Maybe Int
digit i s | i > 9 || i < 0 = Nothing
        | otherwise      = do
    let (c:_) = s
    if read [c] == i then Just i else Nothing
hexChar :: String -> Maybe (Char, String)
hexChar s = alphaParse s `mplus` digitParse s -- cannot switch these to parsers around!!
    where alphaParse s = msum $ map ($ s) (map char (['a'..'f'] ++ ['A'..'F']))
          digitParse s = do let (c':s') = s
                            x <- msum $ map ($ s) (map digit [0..9])
                            return (intToDigit x, s')
if read [c] == i then Just i else Nothing

标记的代码有缺陷。你用的是IntRead实例,例如read :: String -> Int。但是如果不可能将[c]解析为int(例如"a"), read将抛出异常:

>数字1 "不以数字开头"***例外:前奏。阅读:无解析>——另一个例子> (read:: String -> Int)"一个"***例外:前奏。阅读:无解析之前

相反,用另一种方式:

if [c] == show i then Just i else Nothing

这将始终有效,因为show不会失败(不包括涉及bottom的情况)。

最新更新