[英]Haskell: How to check that a char is valid utf8
如何檢查 haskell 中的Char
是否是有效的 UTF8 代碼點?
我有一個 class 正在生成字符串,受一些約束,以及該 class 的Arbitrary
實例(僅生成滿足這些約束的字符串)。 我正在使用GenValidity
。 但是 String 的標准生成器偶爾會生成無效字符; 例如'\xed'
。 不出所料,這會在以后引起問題。
“無效”是指Data.Text.Encoding.streamDecodeUtf8
標記錯誤:
λ> streamDecodeUtf8 (Data.ByteString.Char8.pack "\xed")
Some "" "\237" _
我想向我的 GenValidity 實例添加一個基於(假設的) isValidUTF8:: Char -> Bool
function 的約束,但令人驚訝的是,我找不到任何匹配項。 我能做的最好的ATM是
((\ (Data.Text.Encoding.Some _ x _) -> x /= "") . Data.Text.Encoding.streamDecodeUtf8With (\ _ _ -> Nothing) . Data.ByteString.Char8.pack) . pure
這肯定是相當重量級的,我擔心轉換為 ByteString,然后轉換為 Text,可能會引入尖銳的邊緣。
我很驚訝我找不到更好的/預先罐裝的東西。
歡迎咨詢和指點!
這些示例按預期工作。
“如何檢查Char
是否為有效的 UTF-8”這個問題沒有任何意義(但你不能因為不知道你不知道什么而受到責備)。 它基於對 UTF-8 是什么的誤解。 UTF-8 是一種編碼:它描述了一種將這些代碼點轉換為字節的方法,這些字節可以存儲或通過網絡發送。
打個比方,這就像問“如何檢查Integer
是否有效以 10 為基數”。 想想為什么這沒有意義。
編碼是“具體數據”的屬性,如“字節串”(字節序列,這是 Haskell 中的ByteString
類型)。 一旦這些字節被解碼,我們就只有“文本”,並且 UTF-8 不再是該抽象級別的相關概念(代碼點序列( Char
),這是 Haskell 中的Text
或String
)。
但是 String 的標准生成器偶爾會生成無效字符; 比如'\xed'。
所有Char
都有效[1] Unicode 代碼點。 ( 參見文檔。 ) '\xed'
是代碼點編號 237。
[1]:對於“有效”的一些定義...... Unicode 隱藏了很多復雜性。
“無效”是指
Data.Text.Encoding.streamDecodeUtf8
標記錯誤:λ> streamDecodeUtf8 (Data.ByteString.Char8.pack "\xed") Some "" "\237" _
streamDecodeUtf8
旨在應用於 UTF-8 字節串,但Data.ByteString.Char8.pack
不會產生 UTF-8。 Char8.pack
更像是一種模擬字節串文字的技巧; 它濫用 Unicode 來解決這樣一個事實,即在 Haskell 中,只有 Unicode 字符串的文字。 但是在這里你不想生成任意字節,所以不要使用Char8.pack
。
要對文本進行編碼,請使用Data.Text.Encoding
模塊中的編碼函數之一。 正如我們所看到的,不同的編碼有不同的功能,這進一步說明了“編碼”不是文本固有的屬性,而是與它在 memory( ByteString
公開)中的表示有關。
ghci> import Data.Text (pack)
ghci> import Data.Text.Encoding
ghci> streamDecodeUtf8 (encodeUtf8 (Data.Text.pack "\xed"))
Some "\237" "" _
我很驚訝我找不到更好的/預先罐裝的東西。
關於 Haskell 中的文本和整個編程有很多抱怨,但在這種情況下,問題源於對 Unicode 的誤解。 錯不在你身上,如果你還不熟悉這個系統,它肯定不明顯。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.