CodeWash
CodeWash

Reputation: 185

Neater binary file processing in Haskell

This is a general question inspired by a particular piece of code I wrote that I'm not happy with. I'm using Data.Binary.Get to grab some data from a binary file. Some of the code looks a bit like this

import Data.Binary.Get

data Thing = Thing
  {
    aaa :: Integer,
    bbb :: Integer,
    ccc :: Integer
  } deriving (Show)

getThing :: Get Thing
getThing = do
  laaa <- getWord8 >>= \x -> return (toInteger x)
  lbbb <- getWord16host >>= \x -> return (toInteger x)
  lccc <- getWord32host >>= \x -> return (toInteger x)
  return $ Thing laaa lbbb lccc

The "getThing" function is really long. I am hoping there is a nice way to do something like the following pseudocode or maybe something even more concise.

[laaa, lbbb, lccc] <- MAGIC [getword8, getword16, getWord32] >>= \x -> return (toInteger x)

What have you got?

Upvotes: 1

Views: 60

Answers (1)

Bergi
Bergi

Reputation: 665456

I would write

getThing :: Get Thing
getThing = Thing <$> intFrom getWord8 <*> intFrom getWord16 <*> intFrom getWord32
  where
    where intFrom x = toInteger <$> x

The magic you are looking for is known as sequence, but you can't put IO Word8, IO Word16 and IO Word32 in the same list:

getThing :: Get Thing
getThing = do
  [laaa, lbbb, lccc] <- sequence [toInteger <$> getword8, toInteger <$> getword16, toInteger <$> getWord32]
  return $ Thing laaa lbbb lccc

Upvotes: 4

Related Questions