1

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?

1 Answer 1

4

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
Sign up to request clarification or add additional context in comments.

4 Comments

Also, note that for the version using the shorthand intFrom, for obscure reasons you'll need to either turn on the {-# LANGUAGE NoMonomorphismRestriction #-} pragma or give intFrom an explicit type signature (e.g., intFrom :: (Functor f, Integral a) => f a -> f Integer).
Thanks! I went with your first suggestion. It's much easier to read than what I had when laid out over multiple lines with comments on each line.
@K.A.Buhr Thanks, I completely forgot about that. Not putting intFrom in a top-level declaration should work as well, right?
@Bergi, that would have the same problem, as I think you discovered. But an even nicer solution is probably to write where intFrom x = toInteger <$> x. Giving intFrom an explicit argument changes the typing rules slightly, so the monomorphism restriction no longer applies.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.