views:

321

answers:

3

Construct is a DSL implemented in Python used to describe data structures (binary and textual). Once you have the data structure described, construct can parse and build it for you. Which is good ("DRY", "Declarative", "Denotational-Semantics"...)

Usage example:

# code from construct.formats.graphics.png
itxt_info = Struct("itxt_info",
  CString("keyword"),
  UBInt8("compression_flag"),
  compression_method,
  CString("language_tag"),
  CString("translated_keyword"),
  OnDemand(
    Field("text",
      lambda ctx: ctx._.length - (len(ctx.keyword) + 
      len(ctx.language_tag) + len(ctx.translated_keyword) + 5),
    ),
  ),
)

I am in need for such a tool for Haskell and I wonder if something like this exists.

I know of:

  • Data.Binary: User implements parsing and building seperately
  • Parsec: Only for parsing? Only for text?

I guess one must use Template Haskell to achieve this?

A: 

I don't know anything about Python or Construct, so this is probably not what you are searching for, but for simple data structures you can always just derive read:

data Test a = I Int | S a deriving (Read,Show)

Now, for the expression

read "S 123" :: Test Double

GHCi will emit: S 123.0

For anything more complex, you can make an instance of Read using Parsec.

fishlips
I think you meant *emit* not *omit*.
rampion
@rampion: Yep, you are right, I corrected it. Thank you!
fishlips
@fishlips: Construct allows you to parse specific file-formats/protocols. If you just define a type that is equivalent to the data contained in a PNG file, its `read` will not parse PNG files. Parsec doesn't solve my problem because I want to describe the format once and then be able to both parse and build it, not just parse.
yairchu
+1  A: 

I'd say it depends what you want to do, and if you need to comply with any existing format.

Data.Binary will (surprise!) help you with binary data, both reading and writing. You can either write the code to read/write yourself, or let go of the details and generate the required code for your data structures using some additional tools like DrIFT or Derive. DrIFT works as a preprocessor, while Derive can work as a preprocessor and with TemplateHaskell.

Parsec will only help you with parsing text. No binary data (as easily), and no writing. Work is done with regular Strings. There are ByteString equivalents on hackage.

For your example above I'd use Data.Binary and write custom put/geters myself. Have a look at the parser category at hackage for more options.

L. Kolmodin
@L. Kolmodin: thanks. if I understand correctly then DrIFT and Derive automatically derive instances for me. meaning that I cannot specify in what way I want the data to be formatted. No package in the parsing category seems to do what I need. The only thing I found similar to Construct is "Pickling Combinators" (http://research.microsoft.com/~akenn/fun/picklercombinators.pdf).
yairchu
@yairchu: Yes, DrIFT and Derive will automatically derive the instances.http://hackage.haskell.org/package/BitSyntax may also be of interest, seems similar to your example, although I don't know how stable it is.API here: http://hackage.haskell.org/packages/archive/BitSyntax/0.3.2/doc/html/Data-BitSyntax.html
L. Kolmodin
A: 

Currently (afaik) there is no equivalent to Construct in Haskell.

One can be implemented using Template Haskell.

yairchu