也许MonadPlus解析器需要按特定顺序排列吗?

时间:2014-07-08 11:04:50

标签: haskell

我在wikibooks/haskell上练习练习,MonadPlus-chapter中有一个练习要求你编写这个hexChar函数。我的函数如下所示工作,但事实是,当我尝试切换2个辅助解析器(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')

1 个答案:

答案 0 :(得分:3)

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

标记的代码有一个缺陷。您正在使用Int的{​​{1}}个实例,例如Read。但如果无法将read :: String -> Int解析为int(例如[c]),则"a"会抛出异常:

> digit 1 "doesnt start with a digit"
*** Exception: Prelude.read: no parse
> -- other example
> (read :: String -> Int) "a"
*** Exception: Prelude.read: no parse

相反,走另一条路:

read

这将始终有效,因为if [c] == show i then Just i else Nothing不会失败(不计算涉及底部的情况)。