2014-07-08 31 views
2

我正在通過練習wikibooks/haskell進行練習,並且在MonadPlus-chapter中有一個練習,它要求您編寫這個hexChar函數。我的函數如下所示,但是當我嘗試切換函數週圍的2個幫助器解析器(digitParse和alphaParse)時,它停止正常工作。如果我切換它們,我只能解析數字而不是字母字符。也許MonadPlus解析器需要以某種順序?

這是爲什麼呢?

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') 

回答

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

所標記的代碼有一個缺陷。您正在使用IntRead實例,例如read :: String -> Int。但是,如果它無法解析[c]爲int(如"a"),read將拋出一個異常:

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

相反,走另一條路:

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

這將始終工作,因爲show將不會失敗(不包括涉及底部的情況)。

+1

另外,還有一個函數'readMaybe',它返回'Read a =>也許是',因爲它存在於Maybe'monad中,所以我喜歡使用它。 – bheklilr