[Haskell-beginners] Extract and integer from a ByteString

Stephen Tetley stephen.tetley at gmail.com
Wed Jun 16 06:18:28 EDT 2010


On 16 June 2010 08:40, Tom Hobbs <tvhobbs at googlemail.com> wrote:
> Hi Stephen,
>
> Thanks for the answer, I shall give it a go later tonight (UK time).
> Why would I want to keep my functions monadic?  It's not that I'm against
> the idea, rather it's that I don't understand the choice.  I was under the
> (possibly wrong) impression that (IO) monadic functions were just to "get
> around" the issue of side-effects and that where possible functions should
> be coded outside of monads.  Is that just plain wrong, or does it boil down
> to "It depends on what you're doing, and in this case..."?

Hi Tom


Yes - its a "depend on what your doing" thing...

For reading binary data, having a set of functions to read different
types of data provides a nice interface. Data.Binary.Get provides some
- e.g. getWord8, getWord32,... - and they are all in the Get monad.
For a particular domain you would want to
construct the parsers for that domain - but still keep them in the Get
monad so you would keep the uniform interface.

E.g., say if you had a structure for IP address, stored without the dots:

data IPAddr = IPAddr Word8 Word8 Word8 Word8

getIPAddr :: Get IPAddr
getIPAdde = do
  { a <- getWord8
  ; b <- getWord8
  ; c <- getWord8
  ; d <- getWord8
  ; return (IPAddr a b c d)
  }

In you original code, the extractInt function is a good candidate to
be a "Get" function rather than a a function that turns [Word8] data
into an Int - i.e. I would make it do some parsing work rather than
just the data conversion. As you are always reading 4 bytes and its
big endian (I think?), I would adapt the existing getWord32be parser:

extractInt :: Get Int
extractInt = do
  { a <- getWord32be
  ; return (fromIntegral a)
  }

Or more succinctly:

extractInt :: Get Int
extractInt = liftM fromIntegral getWord32be

liftM, liftM2 are a family of functions that post-process the value
(or values) returned from monadic operation(s) with a pure function
(here fromIntegral).

Of course, this will mean that the other code will have to be changed
to use Data.Binary.Get but the end result should be cleaner code.

> Also I think I've already encountered the hidden Data.Binary problem in GHC.
>  I have got around it already by (if memory serves) starting GHC and telling
> it to ignore it's own Data.Binary so I can then include it in my own
> projects.  But I created an alias which starts this Data.Binary-capable GHC
> and I can't remember what's behind it now!
> What's the reason for GHC hiding packages and preventing them from being
> imported/used in loaded projects?

GHC used to ship with a lot of libraries, but that was a large
maintenance effort and now the Haskell Platform does this job.
However, GHC is self-contained, so it still ships versions of the
third-party libraries it uses internally (base, containers, the
cabal-libraries but not the "cabal install" the tool...). I think
Data.Binary is a more recent dependency, and its perhaps just an
accident that it is half in / half out.

Best wishes

Stephen


More information about the Beginners mailing list