liveBook · Manning

ByteString

As explained in Learn Haskell by Example

ByteString is a Haskell byte-sequence type provided in strict and lazy variants.

ByteString is a packed, list-like sequence of bytes. Its elements are Word8 values: unsigned 8-bit integers from 0 to 255. It is suited to binary input and performance-sensitive string data, where String uses heap-allocated linked lists with poor cache locality. section 12.2 section 6.3.2

ByteString has functions similar to Text, but it is not an ordinary list: usual list functions do not apply directly. Convert between Char and Word8 with c2w and w2c when needed. String literals can be interpreted as ByteString through its IsString instance. section 12.2

Use ByteString when working directly with bytes:

  • Parse binary formats such as PNM pixel data with Data.Attoparsec.ByteString. Attoparsec parsers consume ByteString and can accept incremental input through Partial results. section 12.2.1
  • Read only the required prefix of a file handle with Data.ByteString.hGet, which returns a ByteString and does not fail at EOF. section 14.2
  • Inspect a file signature by unpacking its bytes to [Word8] and pattern matching on magic-number prefixes. section 14.2
  • Consider it after algorithm and data-structure choices have been addressed; replacing String alone may offer only a marginal improvement. section 6.3.2

Recognizing a file type

Read up to eight bytes from a handle with BS.hGet, unpack the result, then match prefixes such as 0x42 : 0x4d for a bitmap or 0x1f : 0x8b for gzip. This avoids reading an entire file merely to inspect its signature. section 14.2

Listing 14.1 An insecure example of reading from a file handle
determineFileType :: FilePath -> IO FileType
determineFileType path = do
  hdl <- openFile path ReadMode  #1
  signature <- BS.hGet hdl 8  #2
  let fileType = case BS.unpack signature of  #3
        0x42 : 0x4d : _ -> Image
        0x89 : 0x50 : 0x4e : 0x47 : 0x0d : 0x0a : 0x1a : 0x0a
 : _ -> Image
        0xff : 0xd8 : 0xff : _ -> Image
        0x42 : 0x5a : 0x68 : _ -> Compressed
        0x1f : 0x8b : _ -> Compressed
        _ -> Other
  hClose hdl            #4
  return fileType  #5

This implementation reads a short ByteString signature, converts it to bytes with unpack, and classifies several image and compressed formats by prefix. section 14.2

How Learn Haskell by Example covers it

How deep it goes
Defines Word8-based representation and demonstrates parsing and handle reads, while deferring a detailed String replacement.
Examples
Uses PNM parsing, incremental Hello parsing, and magic-number classification for image and compressed files.
What it assumes
Introduces bytes as Word8 values and supplies Char conversion helpers for ordinary character-oriented code.
What you can do after
Apply it via Data.ByteString and Attoparsec to read byte prefixes and parse binary input.
How it connects
Connects ByteString with String, Text, Word8, Attoparsec, Handle, and magic numbers.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Haskell by Example. The section links point to the parts of the book it draws on.