Jump to content
Main menu
Main menu
move to sidebar
hide
Navigation
Haskell
Wiki community
Recent changes
Random page
HaskellWiki
Search
Search
Create account
Log in
Personal tools
Create account
Log in
Pages for logged out editors
learn more
Contributions
Talk
Editing
Dealing with binary data
(section)
Page
Discussion
English
Read
Edit
View history
Tools
Tools
move to sidebar
hide
Actions
Read
Edit
View history
General
What links here
Related changes
Special pages
Page information
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
==== Strict <tt>Get</tt> monad ==== If you're parsing small messages then, firstly your input isn't going to be a lazy bytestring but a strict one. That's not reallly a problem because you can easilly convert between them. However, if you want to handle parse failures you either have to write your parser very carefully, or you have to deal with the fact that you can only catch exceptions in the IO monad. If this is your dilemma, then you need a strict version of the <tt>Get</tt> monad. It's almost exactly the same, but a parser of type <hask>Get a</hask> results in <hask>(Either String a, ByteString)</hask> as the result of <hask>runGet</hask>. That type is a tuple where the first value is ''either'' a string (an error string from the parse) or the result, and the second value is the remaining bytestring when the parser finished. Let's update the first example with this strict version of <tt>Get</tt>. You'll have to install the [http://hackage.haskell.org/package/binary-strict binary-strict] package for it to work. <haskell>import qualified Data.ByteString as B import Data.Binary.Strict.Get import Data.Word deserialiseHeader :: Get (Word32, Word32, Word32) deserialiseHeader = do alen <- getWord32be plen <- getWord32be chksum <- getWord32be return (alen, plen, chksum) main :: IO () main = do input <- B.getContents print $ runGet deserialiseHeader input</haskell> Note that all we've done is change from lazy bytestrings to strict bytestrings and change to importing <tt>Data.Binary.Strict.Get</tt>. Now we'll run it again: <pre>% runhaskell /tmp/example.hs << EOF heredoc> 123412341235 heredoc> EOF (Right (825373492,825373492,825373493),"\n")</pre> Now we can see that the parser was successful (we got a <tt>Right</tt>) and we can see that our shell actually added an extra newline on the input (correctly) and the parser didn't consume that, so it's also returned to us. Now we try it with a truncated input: <pre>% runhaskell /tmp/example.hs << EOF heredoc> tooshort heredoc> EOF (Left "too few bytes","\n")</pre> This time we didn't get an exception, but a <tt>Left</tt> value, which can be handled in pure code. The remaining bytestring is the same because our truncated input is 9 bytes long, parsing the first two <tt>Word32</tt>'s consumed 8 bytes and parsing the third failed—at which point we had the last byte still in the input. In your parser, you can also call <hask>fail</hask>, with an error string, which will result in a <tt>Left</tt> value. That's it; it's otherwise the same as the <tt>Get</tt> monad.
Summary:
Please note that all contributions to HaskellWiki are considered to be released under simple permissive license (see
HaskellWiki:Copyrights
for details). If you don't want your writing to be edited mercilessly and redistributed at will, then don't submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource.
DO NOT SUBMIT COPYRIGHTED WORK WITHOUT PERMISSION!
Cancel
Editing help
(opens in new window)
Toggle limited content width