Help us understand the problem. What is going on with this article?

HaskellでのQuickCheckとData.ByteString.Char8の罠

More than 1 year has passed since last update.

URL変換を伴う部分でQuickCheckで以下のようなコードをテストしていたときです。

-- SBS = Data.ByteString.Char8
spec :: Spec
spec = do
  prop " urlEncode/urlDecode" $
    \t -> t == (SBS.unpack . urlDecode . urlEncode . SBS.pack) t

こんな失敗が出ました。

test/Network/Api/UrlSpec.hs:20:3: 
  18) Network.Api.Url  urlEncode/urlDecode
       Falsifiable (after 3 tests and 1 shrink):
         "\883916"

\883916という値で失敗しているようです。ちょっとghciでチェックしてみましょう。

Prelude Network.HTTP.Types.URI> urlDecode $ urlEncode "\883916"
"\204"

もとの数から変化している……?これはなんとなくピンときました。内部でUTF-32を使っているのでエスケープしたとき\x10ffffまで取ることができるのです。
UTF-32 - Wikipedia
で、ByteStringは内部的には[Word8]ですからこれをこの文字(\883916)をWord8に突っ込もうとします。もちろん255までしか突っ込めません。するとどうなるのかと言うと、なんとHaskell側で勝手に下位8ビット以外捨ててしまい無理やり0x00~0xffの範囲に収めてしまうのです。

それはともかくなぜこんなことが起こったのか……。ByteStringChar8バージョンなのがミソでしたQuickCheckはテストデータとして任意のStringは作ってくれますが、任意のByteStringは作ってくれません。[Word8]なら任意のデータを作ってくれるのでそれをpackしてByteStringを作っていました。

そしてどこかのタイミングで「おっ、このData.ByteString.Char8って便利じゃーん」とか思いそれに変えました。Data.ByteString.Char8packString -> ByteString、つまりQuickCheckでテストデータを生成しようとするとUTF-32[Char]が生成され、それが[Word8]にまとめられる……というわけでした。

A_kirisaki
アッキーでーす✨普段は絵とか漫画🎨書いたりしてますけど、プログラミングもやってまーす✌バックエンドからフロントエンドにデザイン、女装まで何でもやります🔥
https://klara.works
realglobe
「世界のすべてをWebAPI化する」ことを目指す技術ベンチャーです。
https://realglobe.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした