Reducing boilerplate of binary layout handling in Haskell Here is the code: https://github.com/EarlGray/haskell-snippets/blob/master/ext2hs/Ext2.hs

My problem is that it is quite painful to make large Haskell "records" and deserialize a binary layout with Data.Binary.Get manually like this:

instance Binary Superblock where
  get = binGetSuperblock

binGetSuperblock = do
  uint13  &lt;- replicateM 13   getWord32le
  ushort6 &lt;- replicateM 6    getWord16le
  uint4   &lt;- replicateM 4    getWord32le
  ushort2 &lt;- replicateM 2    getWord16le
  return Superblock {
    sInodesCount = uint13 !! 0,           sBlocksCount = uint13 !! 1,
    sReservedBlocksCount = uint13 !! 2,   sFreeBlocksCount = uint13 !! 3,
    sFreeInodesCount = uint13 !! 4,       sFirstDataBlock = uint13 !! 5,
    sLogBlockSize = uint13 !! 6,          sLogClusterSize = uint13 !! 7,
    sBlocksPerGroup = uint13 !! 8,        sClustersPerGroup = uint13 !! 9,
    sInodesPerGroup = uint13 !! 10,       sMountTime = uint13 !! 11,
    sWriteTime = uint13 !! 12,

    sMountsCount = ushort6 !! 0,    sMaxMountsCount = int (ushort6 !! 1),
    sMagic = ushort6 !! 2,          sState = ushort6 !! 3,
    sErrors = ushort6 !! 4,
    sLastCheckTime = uint4 !! 0,    sCheckInterval = uint4 !! 1,
    sCreatorOS = uint4 !! 2,        sRevLevel = (uint4 !! 3, ushort6 !! 5),

    sDefaultResUID = ushort2 !! 0,  sDefaultResGID = ushort2 !! 1,

    sDynRev = Nothing,
    sPrealloc = Nothing,
    sJournaling = Nothing
  }


(this is ext2fs superblock structure).

First of all, I would like to make binary layout as much declarative as possible, abstracting away those ugly sequences of getWord32le in Get monad with temporary fields. I want something like my python code, where binary fields are unpacked to a map according to a struct format string

The second thing I need is a more concise and more clear way for initializing a large Haskell record (creating a lot of temporary named values in the monad is pain).

One way I think of is to read binary fields into a heterogeneous map forall a. BinaryField a =&gt; Map String a, accessing each value by its name and pre-extracting most used ones to Haskell.
Perhaps Template Haskell and code generation from a declarative format may help, but I have no experience with TH yet. 

I would be glad to hear any suggestions or hints about a more idiomatic way (are there any relevant tools?) or about the code in general (though it's just my learning code and it's very incomplete at the moment).
To add one more suggestion - building records can be simplified quite a bit by using the RecordWildCards extension, which automatically populates fields from visible names (see GHC docs). Personally, I consider it borderline essential for dealing with large records. I would probably write this like follows:

{-# LANGUAGE RecordWildCards #-}
-- ...
binGetSuperblock = do
  [sInodesCount,         sBlocksCount,
   sReservedBlocksCount, sFreeBlocksCount,
   sFreeInodesCount,     sFirstDataBlock,
   sLogBlockSize,        sLogClusterSize,
   sBlocksPerGroup,      sClustersPerGroup,
   sInodesPerGroup,      sMountTime,
   sWriteTime]                            &lt;- replicateM 13 getWord32le
  [sMountsCount,         sMaxMountsCount,
   sMagic,               sState,
   sErrors,              sRevLevel2]      &lt;- replicateM 6  getWord16le
  [sLastCheckTime,       sCheckInterval,
   sCreatorOS,           sRevLevel1]      &lt;- replicateM 4  getWord32le
  [sDefaultResUID,       sDefaultResGID]  &lt;- replicateM 2  getWord16le
  return Superblock {
    sMaxMountsCount = int sMaxMountsCount,
    sRevLevel = (sRevLevel1, sRevLevel2),
    sDynRev = Nothing,
    sPrealloc = Nothing,
    sJournaling = Nothing,
    ..
    }