Haskell:如何将"\\ 0"变成"\ 0"?

Sno*_*ual 5 string haskell escaping

Haskell有许多使用\转义序列的字符串文字.的,如\n,\t,\NUL.

如果我有字符串文字:

let s = "Newline: \\n Tab: \\t"
Run Code Online (Sandbox Code Playgroud)

如何定义escape :: String -> String将上述字符串转换为的函数:

"Newline: \n Tab: \t"
Run Code Online (Sandbox Code Playgroud)

与所有其他字符串文字转义序列相同.

我可以使用Quasi Quoting和Template Haskell,但不知道如何使用它们来实现结果.有什么指针吗?


更新:我刚刚找到了包含在Base库中的Text.ParserCombinators.ReadP模块.它支持readLitChar :: ReadS CharData.Char中的功能,它可以实现我想要的功能,但我不知道如何使用ReadP模块.我尝试了以下功能:

escape2 [] = []
escape2 xs = case readLitChar xs of
    [] -> []
    [(a, b)] -> a : escape2 b
Run Code Online (Sandbox Code Playgroud)

但这可能不是使用ReadP模块的正确方法.任何人都可以提供一些指示吗?

另一个更新:谢谢大家.我的最终功能如下.不错,我想.

import Text.ParserCombinators.ReadP
import Text.Read.Lex

escape xs 
    | []      <- r = []
    | [(a,_)] <- r = a
    where r = readP_to_S (manyTill lexChar eof) xs 
Run Code Online (Sandbox Code Playgroud)

Joh*_*n L 6

你不需要做任何事情.输入字符串文字时

let s = "Newline: \\n Tab: \\t"
Run Code Online (Sandbox Code Playgroud)

你可以检查它是你想要的:

Prelude> putStrLn s
Newline: \n Tab: \t
Prelude> length s
19
Run Code Online (Sandbox Code Playgroud)

如果你只是问ghci的价值,s你会得到别的东西,

Prelude> s
"Newline: \\n Tab: \\t"
Run Code Online (Sandbox Code Playgroud)

显然它正在你背后做一些逃避格式化,它也显示引号.如果你打电话show或者print你还会得到其他答案:

Prelude> show s
"\"Newline: \\\\n Tab: \\\\t\""
Prelude> print s
"Newline: \\n Tab: \\t"
Run Code Online (Sandbox Code Playgroud)

这是因为show用于序列化值,所以当你show没有得到原始字符串的字符串时,你会得到一个序列化字符串,可以将其解析为原始字符串.结果show s实际显示为print s(print定义为putStrLn . show).当你只是show s在ghci你得到一个更奇怪的答案; 这里ghci正在格式化序列化的字符show.

tl; dr - 总是putStrLn用来查看字符串在ghci中的值.

编辑:我刚才意识到你想要转换字面值

Newline: \n Tab: \t
Run Code Online (Sandbox Code Playgroud)

进入实际的控制序列.最简单的方法是将它粘在引号中并使用read:

Prelude> let s' = '"' : s ++ "\""
Prelude> read s' :: String
"Newline: \n Tab: \t"
Prelude> putStrLn (read s')
Newline: 
 Tab:   
Run Code Online (Sandbox Code Playgroud)

编辑2:使用的一个例子readLitChar,这非常接近克里斯的答案,除了readLitChar:

strParser :: ReadP String
strParser = do
  str <- many (readS_to_P readLitChar)
  eof
  return str
Run Code Online (Sandbox Code Playgroud)

然后你运行它readP_to_S,它给你一个匹配的解析列表(不应该有多个匹配,但是可能没有任何匹配,所以你应该检查一个空列表.)

> putStrLn . fst . head $ readP_to_S strParser s
Newline:
Tab:    
>
Run Code Online (Sandbox Code Playgroud)