我正在写一个parsec分析器,它读取字符串并转换转义字符,作为练习3 here的一部分。Haskell:字符转义的字符
为了锻炼我使用这个功能:
escapedCharFromChar :: Char -> Char
escapedCharFromChar c = read $ concat ["'\\",[c],"'"]
我不是深刻的印象使用read
的字符x
转换成转义字符的名称x
。任何人都可以提出一个更优雅的功能Char -> Char
这样做吗?
我正在写一个parsec分析器,它读取字符串并转换转义字符,作为练习3 here的一部分。Haskell:字符转义的字符
为了锻炼我使用这个功能:
escapedCharFromChar :: Char -> Char
escapedCharFromChar c = read $ concat ["'\\",[c],"'"]
我不是深刻的印象使用read
的字符x
转换成转义字符的名称x
。任何人都可以提出一个更优雅的功能Char -> Char
这样做吗?
的方法之一是详尽铺陈情况:
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 something
(即,c
在escapes
的条目),但是这会散架时假设是无效的:
ghci> charFromEscape 'r' *** Exception: Maybe.fromJust: Nothing
这些例子会在练习中让你感动,但很明显你会喜欢更好的错误处理。此外,如果您希望查找表很大,您可能需要查看Data.Map。
我刚刚使用了模式匹配方法来处理我关心的几个逃跑 - 也就是't' -> '\t'
等。其他读者提出的解决方案是相似的。不是非常通用的,但非常直接。
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。
这是一个耻辱'lexEscChar'没有出口,否则这将是一个完美的答案。尽管感谢您的领导。 – dukedave 2010-08-25 17:03:34