2010-08-24 128 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