2010-08-24 124 views
2

我正在寫一個parsec分析器,它讀取字符串並轉換轉義字符,作爲練習3 here的一部分。Haskell:字符轉義的字符

爲了鍛鍊我使用這個功能:

escapedCharFromChar :: Char -> Char 
escapedCharFromChar c = read $ concat ["'\\",[c],"'"] 

我不是深刻的印象使用read的字符x轉換成轉義字符的名稱x。任何人都可以提出一個更優雅的功能Char -> Char這樣做嗎?

回答

5

的方法之一是詳盡鋪陳情況:

charFromEscape :: Char -> Char 
charFromEscape 'n' = '\n' 
charFromEscape 't' = '\t' 
--- ... --- Help! 

您還可以使用lookup

-- this import goes at the top of your source file 
import Data.Maybe (fromJust) 

charFromEscape :: Char -> Char 
charFromEscape c = fromJust $ lookup c escapes 
    where escapes = [('n', '\n'), ('t', '\t')] -- and so on 

fromJust位可能看起來很奇怪。該類型的lookup

lookup :: (Eq a) => a -> [(a, b)] -> Maybe b 

這意味着超過其平等是指某種類型的值和查找表,它想給你從查找相應的值表,但你的鑰匙不能保證出現在桌子上!這就是Maybe目的,其定義是

data Maybe a = Just a | Nothing 

隨着fromJust,它假定你有Just somethingcescapes的條目),但是這會散架時假設是無效的:

ghci> charFromEscape 'r' 
*** Exception: Maybe.fromJust: Nothing

這些例子會在練習中讓你感動,但很明顯你會喜歡更好的錯誤處理。此外,如果您希望查找表很大,您可能需要查看Data.Map

1

我剛剛使用了模式匹配方法來處理我關心的幾個逃跑 - 也就是't' -> '\t'等。其他讀者提出的解決方案是相似的。不是非常通用的,但非常直接。

6

read(或者說,Text.Read.Lex.lexCharE)是你如何讓在GHC's internal table,其定義爲:

lexEscChar = 
    do c <- get 
     case c of 
     'a' -> return '\a' 
     'b' -> return '\b' 
     'f' -> return '\f' 
     'n' -> return '\n' 
     'r' -> return '\r' 
     't' -> return '\t' 
     'v' -> return '\v' 
     '\\' -> return '\\' 
     '\"' -> return '\"' 
     '\'' -> return '\'' 
     _ -> pfail 

最終,你必須從某個地方定義語義。你可以在你的程序中完成,或者你可以重新使用GHC。

+0

這是一個恥辱'lexEscChar'沒有出口,否則這將是一個完美的答案。儘管感謝您的領導。 – dukedave 2010-08-25 17:03:34