writeFile "d" "d" $ cat d d -6ren">
gpt4 book ai didi

haskell - show w.r.t. 的语义转义字符

转载 作者:行者123 更新时间:2023-12-05 00:13:11 27 4
gpt4 key购买 nike

考虑以下示例(λ> = ghci,$ = shell):

λ> writeFile "d" $ show "d"
$ cat d
"d"

λ> writeFile "d" "d"
$ cat d
d

λ> writeFile "backslash" $ show "\\"
$ cat backslash
"\\"

λ> writeFile "backslash" "\\"
$ cat backslash
\

λ> writeFile "cat" $ show "🐈" -- U+1F408
$ cat cat
"\128008"

λ> writeFile "cat" "🐈"
$ cat cat
🐈

我理解 "\128008" 的另一种方式只是另一种表示方式 "🐈"在 Haskell 源代码中。
我的问题是:为什么 "🐈"示例的行为类似于反斜杠而不是
喜欢 "d" ?既然它是一个可打印的字符,它不应该表现得像
一封信?

更一般地说,确定角色是否会成为
显示为可打印字符还是转义码?我看了 Section 6.3
在 Haskell 2010 语言报告中,但它没有指定确切的行为。

最佳答案

TL:博士; ASCII 范围 (0-127) 内的可打印字符将为 show n 作为图形字符。* 其他所有内容都将被转义。

* 双引号除外(因为它们用于字符串分隔符)和
反斜杠(因为转义需要它们)。

让我们看一下源代码来解决这个问题!

因为我们有 String = [Char] ,我们应该寻找 instance Show Char
来源。可以找到
here .
它被定义为:

-- | @since 2.01
instance Show Char where
showsPrec _ '\'' = showString "'\\''"
showsPrec _ c = showChar '\'' . showLitChar c . showChar '\''

showList cs = showChar '"' . showLitString cs . showChar '"'

所以显示 String (使用 showList )基本上是一个包装 ShowLitString ,并显示 CharShowLitChar 的包装器.
让我们看看这些功能。
showLitString :: String -> ShowS
-- | Same as 'showLitChar', but for strings
-- It converts the string to a string using Haskell escape conventions
-- for non-printable characters. Does not add double-quotes around the
-- whole thing; the caller should do that.
-- The main difference from showLitChar (apart from the fact that the
-- argument is a string not a list) is that we must escape double-quotes
showLitString [] s = s
showLitString ('"' : cs) s = showString "\\\"" (showLitString cs s)
showLitString (c : cs) s = showLitChar c (showLitString cs s)
-- [explanatory comments ...]

如您所料, showLitString主要是一个包装 showLitChar .
[注意:如果您不熟悉 ShowS类型,这是一个很好的
answer了解为什么
可能有用。]
不是我们要找的,所以让我们去 showLitChar (我有
省略了与问题无关的定义部分)。
-- | Convert a character to a string using only printable characters,
-- using Haskell source-language escape conventions. For example:
-- [...]
showLitChar :: Char -> ShowS
showLitChar c s | c > '\DEL' = showChar '\\' (protectEsc isDec (shows (ord c)) s)
-- ^ Pattern matched for cat
showLitChar '\DEL' s = showString "\\DEL" s
showLitChar '\\' s = showString "\\\\" s
-- ^ Pattern matched for backslash
showLitChar c s | c >= ' ' = showChar c s
-- ^ Pattern matched for d
-- Some more escape codes
showLitChar '\a' s = showString "\\a" s
-- similarly for '\b', '\f', '\n', '\r', '\t', '\v' etc.
-- showLitChar ... = ...

现在你明白问题出在哪里了。 ord cint , 第一个是
对于所有非 ASCII 字符 ( ord '\DEL' == 127 )。
对于 ASCII 范围内的字符,将打印可打印的字符并
其余的都逃脱了。对于它之外的字符,它们都被转义。

该代码没有回答问题的“为什么”部分。答案
(我认为)在我们看到的第一条评论中:
-- | @since 2.01
instance Show Char where

如果我猜的话,这种行为一直在保持向后保持
兼容性。我不需要猜测:请参阅评论以获得一些好的答案。

奖金

我们可以做一个 git blame在线使用 GHC 的 Github 镜像;)。让我们来看看
编写此代码时
( blame link)。
相关 commit 15 岁(!)。但是,它确实提到了 Unicode。

区分不同类型 Unicode 字符的功能
存在于 Data.Char模块。看着 source :
isPrint    c = iswprint (ord c) /= 0

foreign import ccall unsafe "u_iswprint"
iswprint :: Int -> Int

如果你跟踪引入 iswprint 的提交, 你会降落
here .该 promise 是 13 年前做出的。
也许那两年写了足够多的代码,而他们没有
想打破?我不知道。如果一些 GHC 开发人员可以对此有所了解,
那太棒了:)。 Daniel Wagner 和 Paul Johnson 在评论中指出了一个很好的理由 - 使用非 Unicode 系统必须是一个高优先级(大约 15 年前),因为当时 Unicode 相对较新。

关于haskell - show w.r.t. 的语义转义字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48846437/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com