簡體   English   中英

`Data.Text.Encoding.decodeLatin1` 的倒數?

[英]Inverse of `Data.Text.Encoding.decodeLatin1`?

是否有 function f:: Text -> Maybe ByteString這樣的 forall x

f (decodeLatin1 x) == Just x

請注意, decodeLatin1具有簽名:

decodeLatin1 :: ByteString -> Text

我擔心encodeUtf8不是我想要的,因為我猜它所做的只是將 UTF-8 字符串轉儲為 ByteString,而不是反轉decodeLatin1在進入上半部分字符的過程中所做的更改字符集。

我知道f必須返回一個Maybe ,因為通常有 Unicode 個字符不在拉丁字符集中,但我只希望它至少能夠往返,因為如果我們從ByteString開始,我們應該回到它。

免責聲明:認為這是一個很長的評論而不是一個解決方案,因為我還沒有測試過。

我想你可以用witch library來做。 它是一個具有相當多類型安全性的通用類型轉換器庫。 有一個名為TryFrom的類型 class 用於執行可能無法轉換的類型之間的轉換。

幸運的是, witch也提供從/到 encondings 的轉換,具有一個實例TryFrom Text (ISO_8859_1 ByteString) ,這意味着您可以在Text和 latin1 編碼ByteString之間進行轉換。 所以我認為(未測試!!)這應該有效

{-# LANGUAGE TypeApplications #-}

import Witch (tryInto, ISO_8859_1)
import Data.Tagged (Tagged(unTagged))

f :: Text -> Maybe ByteString
f s = case tryInto @(ISO_8859_1 ByteString) s of
  Left err -> Nothing
  Right bs -> Just (unTagged bs)

注意tryInto返回一個Either TryFromException s ,所以如果你想處理錯誤,你可以用Either來完成。 由你決定。

此外, witch docs 指出這種轉換是通過String類型完成的,因此可能有一個開箱即用的解決方案,無需依賴witch package。我不知道這樣的解決方案,並期待源代碼沒有幫助

編輯:

顯然已經閱讀了witch源代碼,這應該可以工作

import qualified Data.Text as T
import Data.Char (isLatin1)
import qualified Data.ByteString.Char8 as C

f :: Text -> Maybe ByteString
f t = if allCharsAreLatin then Just (C.pack str) else Nothing
 where str = T.unpack t
       allCharsAreLatin = all isLatin1 str

latin1 編碼非常簡單——代碼點 X 映射到字節 X,只要它在一個字節的范圍內。 因此,只需立即打開包裝並重新包裝。

import Control.Monad
import qualified Data.Text as T
import qualified Data.ByteString.Char8 as BS

latin1EncodeText :: T.Text -> Maybe BS.ByteString
latin1EncodeText t = BS.pack (T.unpack t) <$ guard (T.all (<'\256') t)

可以避免中間String ,但在嘗試之前,您可能應該確保這是您的瓶頸。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM