
On 16 June 2010 08:40, Tom Hobbs
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