Spec-Zone.ru › Haskell 7

Data.Binary

Авторские права Lennart Kolmodin
Лицензия BSD3-style (см. LICENSE)
Поддержка Lennart Kolmodin <kolmodin@gmail.com>
Стабильность нестабильная
Переносимость переносимая на Hugs и GHC. Требует FFI и некоторые гибкие экземпляры.
Безопасный Haskell Достоверный
Язык Haskell98

Содержание

  • Класс Binary
    • Пример
  • Поддержка обобщенных типов
  • Монады Get и Put
  • Полезные вспомогательные функции для написания экземпляров
  • Бинарная сериализация
  • Функции IO для сериализации

Описание

Бинарная сериализация значений Haskell в ленивые ByteString и из них. Библиотека Binary предоставляет методы для кодирования значений Haskell в виде потоков байтов непосредственно в памяти. Полученные ByteString затем можно записать на диск, отправить по сети или дополнительно обработать (например, сжать с помощью gzip).

Пакет binary примечателен тем, что он предоставляет как чистую, так и высокопроизводительную сериализацию.

Значения, закодированные с помощью класса Binary, всегда кодируются в сетевом порядке (big endian), и закодированные данные должны быть переносимы через разрядность машины, размер слова или версию компилятора. Например, данные, закодированные с помощью класса Binary, можно было бы записать на любой машине и считать обратно на любую другую.

Если конкретный формат данных для вас не важен, например, вас больше интересует сериализация и десериализация значений, чем формат, который будет использован, можно вывести экземпляры Binary с использованием поддержки обобщенных типов. См. GBinary.

Если у вас есть конкретные требования к формату кодирования, вы можете использовать примитивы кодирования и декодирования напрямую, см. модули Data.Binary.Get и Data.Binary.Put.

Класс Binary

class Binary t where Исходный код

Класс Binary предоставляет методы для кодирования и декодирования значения Haskell в ленивый ByteString. Он отражает классы Read и Show для текстового представления типов Haskell и подходит для сериализации значений Haskell на диск или через сеть.

Для декодирования и генерации простых внешних двоичных форматов (например, структур C) можно использовать Binary, но в целом он не подходит для сложных протоколов. Вместо этого используйте примитивы Put и Get напрямую.

Экземпляры Binary должны удовлетворять следующему свойству:

decode . encode == id

То есть, методы get и put должны быть обратными друг другу. Для базовых типов Haskell предоставляется ряд экземпляров.

Минимальное полное определение

Nothing

Методы

put :: t -> Put Исходный код

Кодирование значения в монаде Put.

get :: Get t Исходный код

Декодирование значения в монаде Get

Экземпляры

Binary Bool
Binary Char
Binary Double
Binary Float
Binary Int
Binary Int8
Binary Int16
Binary Int32
Binary Int64
Binary Integer
Binary Ordering
Binary Word
Binary Word8
Binary Word16
Binary Word32
Binary Word64
Binary ()
Binary Natural
Binary ByteString
Binary ByteString
Binary IntSet
Binary a => Binary [a]
(Binary a, Integral a) => Binary (Ratio a)
Binary a => Binary (Maybe a)
Binary e => Binary (IntMap e)
Binary a => Binary (Set a)
Binary e => Binary (Tree e)
Binary e => Binary (Seq e)
(Binary a, Binary b) => Binary (Either a b)
(Binary a, Binary b) => Binary (a, b)
(Binary i, Ix i, Binary e, IArray UArray e) => Binary (UArray i e)
(Binary i, Ix i, Binary e) => Binary (Array i e)
(Binary k, Binary e) => Binary (Map k e)
(Binary a, Binary b, Binary c) => Binary (a, b, c)
(Binary a, Binary b, Binary c, Binary d) => Binary (a, b, c, d)
(Binary a, Binary b, Binary c, Binary d, Binary e) => Binary (a, b, c, d, e)
(Binary a, Binary b, Binary c, Binary d, Binary e, Binary f) => Binary (a, b, c, d, e, f)
(Binary a, Binary b, Binary c, Binary d, Binary e, Binary f, Binary g) => Binary (a, b, c, d, e, f, g)
(Binary a, Binary b, Binary c, Binary d, Binary e, Binary f, Binary g, Binary h) => Binary (a, b, c, d, e, f, g, h)
(Binary a, Binary b, Binary c, Binary d, Binary e, Binary f, Binary g, Binary h, Binary i) => Binary (a, b, c, d, e, f, g, h, i)
(Binary a, Binary b, Binary c, Binary d, Binary e, Binary f, Binary g, Binary h, Binary i, Binary j) => Binary (a, b, c, d, e, f, g, h, i, j)

Пример

Для сериализации пользовательского типа требуется экземпляр Binary для этого типа. Например, предположим, что у нас есть структура данных:

data Exp = IntE Int
         | OpE  String Exp Exp
   deriving Show

Мы можем кодировать значения этого типа в байтовые строки, используя следующий экземпляр, который рекурсивно разбивает структуру для сериализации:

instance Binary Exp where
      put (IntE i)      = do put (0 :: Word8)
                             put i
      put (OpE s e1 e2) = do put (1 :: Word8)
                             put s
                             put e1
                             put e2

      get = do t <- get :: Get Word8
               case t of
                    0 -> do i <- get
                            return (IntE i)
                    1 -> do s  <- get
                            e1 <- get
                            e2 <- get
                            return (OpE s e1 e2)

Обратите внимание, как мы записываем начальный байт тега, чтобы указать каждый вариант типа данных.

Мы можем упростить запись экземпляров get с помощью монадических комбинаторов:

      get = do tag <- getWord8
               case tag of
                   0 -> liftM  IntE get
                   1 -> liftM3 OpE  get get get

Чтобы сериализовать это в байтовую строку, мы используем encode, которая упаковывает структуру данных в бинарный формат, в ленивую байтовую строку

> let e = OpE "*" (IntE 7) (OpE "/" (IntE 4) (IntE 2))
> let v = encode e

Где v - это бинарно закодированная структура данных. Чтобы восстановить исходные данные, мы используем decode

> decode v :: Exp
OpE "*" (IntE 7) (OpE "/" (IntE 4) (IntE 2))

ленивая ByteString, которая получается из encode, может быть записана на диск и прочитана с диска с помощью функций Data.ByteString.Lazy IO, таких как hPutStr или writeFile:

> writeFile "/tmp/exp.txt" (encode e)

И прочитать обратно с помощью:

> readFile "/tmp/exp.txt" >>= return . decode :: IO Exp
OpE "*" (IntE 7) (OpE "/" (IntE 4) (IntE 2))

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

> v <- decodeFile  "/tmp/exp.txt" :: IO Exp
OpE "*" (IntE 7) (OpE "/" (IntE 4) (IntE 2))

И записать значение на диск

> encodeFile "/tmp/a.txt" v

Универсальная поддержка

Начиная с GHC 7.2, можно использовать бинарную сериализацию без написания какого-либо кода шаблона экземпляра.

{-# LANGUAGE DeriveGeneric #-}

import Data.Binary
import GHC.Generics (Generic)

data Foo = Foo
         deriving (Generic)

-- GHC will automatically fill out the instance
instance Binary Foo

Этот механизм использует эффективную встроенную поддержку универсалов GHC.

class GBinary f where Source

Методы

gput :: f t -> Put Source

gget :: Get (f t) Source

Монады Get и Put

data Get a Source

Примеры

Monad Get
Functor Get
Applicative Get
Alternative Get
MonadPlus Get

type Put = PutM () Source

Put просто поднимает Builder в монаду Writer, применённую к ().

Полезные вспомогательные функции для написания примеров

putWord8 :: Word8 -> Put Source

Эффективно записывает байт в буфер вывода

getWord8 :: Get Word8 Source

Чтение Word8 из состояния монады

Бинарная сериализация

encode :: Binary a => a -> ByteString Source

Кодирование значения с помощью бинарной сериализации в ленивую ByteString.

decode :: Binary a => ByteString -> a Source

Декодирование значения из ленивой ByteString, восстанавливая исходную структуру.

decodeOrFail :: Binary a => ByteString -> Either (ByteString, ByteOffset, String) (ByteString, ByteOffset, a) Source

Декодирование значения из ленивой ByteString. Возвращает Left при неудаче и Right при успехе. В обоих случаях возвращаются неиспользованный вход и количество прочитанных байтов. В случае неудачи также возвращается удобочитаемое сообщение об ошибке.

Функции IO для сериализации

encodeFile :: Binary a => FilePath -> a -> IO () Source

Лениво сериализует значение в файл.

Это просто удобная функция, она определена как:

encodeFile f = B.writeFile f . encode

Например, если вам нужно сжатие, можно использовать:

B.writeFile f . compress . encode

decodeFile :: Binary a => FilePath -> IO a Source

Декодирование значения из файла. В случае ошибок, error будет вызвана с сообщением об ошибке.

decodeFileOrFail :: Binary a => FilePath -> IO (Either (ByteOffset, String) a) Source

Декодирование значения из файла. В случае успеха, значение будет возвращено в Right. В случае ошибок декодера, сообщение об ошибке вместе со смещением байта будут возвращены.

module Data.Word

© The University of Glasgow and others
Licensed under a BSD-style license (see top of the page).
https://downloads.haskell.org/~ghc/7.10.3/docs/html/libraries/binary-0.7.5.0/Data-Binary.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API