寻找Data.Text.Encoding.decodeLatin1的逆函数:Text转Maybe ByteString
问题解答
结论:完全存在这样的函数f
先明确decodeLatin1的核心行为:它会把每个字节(范围0x00到0xFF)直接映射到Unicode码点U+0000到U+00FF,也就是*Latin-1(ISO-8859-1)*字符集对应的所有字符。所以decodeLatin1 x输出的Text里,每个字符的码点必然落在0x00-0xFF区间内。
要实现符合要求的f,逻辑非常直接:
- 遍历输入
Text的每一个字符 - 逐个检查字符的Unicode码点是否在0x00到0xFF之间:
- 如果所有字符都符合条件,就把每个字符的码点转成对应的字节,拼接成
ByteString后用Just包装返回 - 只要有一个字符的码点超出这个范围,直接返回
Nothing
- 如果所有字符都符合条件,就把每个字符的码点转成对应的字节,拼接成
具体实现示例(Haskell)
import Data.Text (Text) import qualified Data.Text as T import Data.ByteString (ByteString) import qualified Data.ByteString as B import Data.Word (Word8) import Data.Maybe (sequence) f :: Text -> Maybe ByteString f txt = B.pack <$> sequence (map charToWord8 (T.unpack txt)) where charToWord8 c = let cp = fromEnum c in if cp >= 0 && cp <= 0xFF then Just (fromIntegral cp :: Word8) else Nothing
为什么encodeUtf8不符合要求?
你的顾虑完全正确。encodeUtf8是把Text按UTF-8编码规则转成ByteString,而decodeLatin1生成的Text里,比如原字节0xA0(非断空格)会被转成U+00A0,用encodeUtf8处理会得到两个字节0xC2 0xA0,和原字节完全不一样,自然没法还原出最初的ByteString。
往返性验证
对于任意ByteString x,decodeLatin1 x得到的Text里每个字符的码点就是原字节的数值(0x00-0xFF),所以f处理这个Text时,所有字符都会通过检查,逐个转成原字节,最终返回Just x,完全满足你要求的往返转换。
内容的提问来源于stack exchange,提问作者Clinton
相关产品推荐
相关产品推荐

