2

wikibooks/haskellの演習に取り組んでいます。MonadPlusの章に、この 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')
4

1 に答える 1

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

マークされたコードには欠陥があります。IntReadインスタンスを使用していますread :: String -> Int[c]ただし、int として解析できない場合(例: "a")、read例外がスローされます。

> 数字 1 「数字で始まっていません」
*** 例外: Prelude.read: 解析なし
> -- その他の例
> (read :: String -> Int) "a"
*** 例外: Prelude.read: 解析なし

代わりに、別の方法に進みます。

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

失敗しないため、これは常に機能showします (底が関係するケースは数えません)。

于 2014-07-08T11:45:02.950 に答える