Многие типы String (ByteString)

Я хочу сжать сетевой трафик моего приложения.

Согласно (последнему?) "Рейтингу популярности Haskell", zlib кажется довольно популярным решением. Интерфейс zlib использует ByteStrings:

compress :: ByteString -> ByteString
decompress :: ByteString -> ByteString

Я использую обычные String, которые также являются типами данных, используемыми read, show и Network.Socket:

sendTo :: Socket -> String -> SockAddr -> IO Int
recvFrom :: Socket -> Int -> IO (String, Int, SockAddr)

Итак, чтобы сжать мои строки, мне нужен способ преобразовать String в ByteString и наоборот. С помощью hoogle я обнаружил:

Data.ByteString.Char8 pack :: String -> ByteString

Пытаюсь использовать:

Prelude Codec.Compression.Zlib Data.ByteString.Char8> compress (pack "boo")

<interactive>:1:10:
    Couldn't match expected type `Data.ByteString.Lazy.Internal.ByteString'
           against inferred type `ByteString'
    In the first argument of `compress', namely `(pack "boo")'
    In the expression: compress (pack "boo")
In the definition of `it': it = compress (pack "boo")

Не удается, потому что (?) Существуют разные типы ByteString?

Итак, в основном:

  • Есть несколько типов ByteString? Какие виды и почему?
  • Каким «способом» преобразовать String в ByteString?

Кстати, я обнаружил, что он работает с Data.ByteString.Lazy.Char8 ByteString, но я все еще заинтригован.


person yairchu    schedule 20.09.2009    source источник


Ответы (3)


Есть два типа строк байтов: строгие (определенные в Data.Bytestring.Internal) и ленивый (определен в Data.Bytestring.Lazy.Internal). Как вы обнаружили, zlib использует ленивые строки байтов.

person Alexey Romanov    schedule 20.09.2009
comment
Нет. Char8 модули просто предоставляют разные интерфейсы для одних и тех же строк байтов. - person Alexey Romanov; 21.09.2009

Функция, которую вы ищете:

import Data.ByteString as BS
import Data.ByteString.Lazy as LBS

lazyToStrictBS :: LBS.ByteString -> BS.ByteString
lazyToStrictBS x = BS.concat $ LBS.toChunks x

Я полагаю, что это можно было бы написать более кратко без x. (т.е. без точек, но я новичок в Haskell.)

person fadedbee    schedule 15.06.2012
comment
как lazyToStrictBS = BS.concat . LBS.toChunks - person sam boosalis; 10.02.2015

Более эффективным механизмом может быть переключение на полный уровень на основе байтовой строки:

  • network.bytestring для сокетов с байтовой строкой
  • ленивые строки байтов для compressoin
  • двоичный файл bytestring-show для замены Show / Read
person Don Stewart    schedule 20.09.2009
comment
@dons: похоже, мне нужно будет использовать Network.Socket.ByteString.Lazy для совместимости с zlib, но, в отличие от Network.Socket.ByteString, он не реализует sendTo и recvFrom, что делает его неподходящим для меня. - person yairchu; 21.09.2009
comment
Я не думаю, что вам будет слишком сложно передавать куски ленивых строк байтов в сокет, беря отдельные строки. По сути, это mapM_ send. fromChunks - person Don Stewart; 21.09.2009
comment
@dons: при использовании UDP на самом деле будет иметь значение, отправляете ли вы свой пакет целиком или по частям. но вы также говорите, что преобразование между ленивым и строгим байтовым циклом легко? что было бы полезно знать .. - person yairchu; 21.09.2009
comment
@yairchu - функции toChunks и fromChunks в Data.ByteString.Lazy конвертируют между строгими и ленивыми строками байтов. - person John L; 15.06.2012