我正在使用该unicode-show
包来进行通过 hspec 测试:
代码:
...(show . Data.List.NonEmpty.head $ infiles2, outFile2) `shouldBe` ("\"/foo/bar/baz - :.ogg\"", outFile1))...
expected: ("\"/foo/bar/baz - :.ogg\"", "/foo/bar/fee.m4a")
but got: ("\"/foo/bar/baz - \\65306.ogg\"", "/foo/bar/fee.m4a")
但随后此代码通过:
...(Text.Show.Unicode.ushow . Data.List.NonEmpty.head $ infiles2, outFile2) `shouldBe` ("\"/foo/bar/baz - :.ogg\"", outFile1))...
Test suite spec: RUNNING...
.........
Finished in 0.0115 seconds
9 examples, 0 failures, 2 pending
Test suite spec: PASS
为什么这是必要的?为什么show
这里不做正确的事情?
的实现者
show @String
有两个设计目标:1. 生成有效的 Haskell 代码,其含义与输入相同 2. 仅使用 7 位干净的 ASCII。(请记住,Haskell 是在 90 年代设计的!我们当时还处于黑暗时代,并非所有软件都支持 Unicode,尤其是终端和电子邮件客户端。)因此,所有高于 127 的代码点都会被转义。您不应该使用
show
来检查两个字符串是否相等。事实上,如果您使用:这将返回
True
,因为两个字符串都包含 20 个字符,并且每个字符都相同。因此您的测试(可能)可以与以下方法配合使用:但是你在这里使用。函数 [Hackage]
show
是什么?它通常用于将对象转换为字符串,该字符串是包含构造代码的字符串。因此,对于类似的,它会产生,如果你在终端中写入,那么你构造了。show :: Show a => a -> String
a
a
Int
5
"5"
5
Int
5
但是构造 的方法有很多种
5
,例如1 + 4
也是5
,但是"5"
和"1 + 4"
并不相同String
。这两个表达式都产生了5
,但是在字符串级别检查时,它们却是不同的字符串。这就是
show
字符串的作用,它将生成一个类似于 的字符串,内容"\"/foo/bar/baz - \\65306.ogg\""
为,请注意,此字符串包含 27 个字符。实际上,特殊冒号字符被转义为,其中包含六个字符,引号字符也被转义为,因此每个引号包含两个字符。"/foo/bar/baz - \65306.ogg"
\65306
\"
unicode 字符本身不需要转义,因此如果转义方式不同,则会得到两个不同的结果,因此字符串不同,因此测试失败。
因此,检查两个
show
s 的等价性不能保证有效,因为两个表达式可以构造相同的值,但表达式不同。事实上ushow
,如果您使用以下方法,也不会正常工作:这本来可以
show
奏效的地方却失败了。因此,经验法则是:不要使用
show
来检查两个值的等价性。尝试使用 来检查(==) :: Eq a => a -> a -> Bool
实际值。通常使用 的结果show
容易出错:必须遵循show
(或ushow
)用于将值编码为字符串的确切规则,并且它可能受到(伪)随机性的影响,例如在哈希集的情况下。