Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7979541
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 4, 20262026-06-04T09:48:21+00:00 2026-06-04T09:48:21+00:00

I have a lot of code like this: data Post = Post { postOwner

  • 0

I have a lot of code like this:

data Post =
    Post
    { postOwner :: Integer
    , postText :: ByteString
    , postDate :: ByteString
    }

sqlToPost :: [SqlValue] -> Post
sqlToPost [owner, text, date] = Post (fromSql owner) (fromSql text) (fromSql date)

(Library used here is HDBC). In future, there will be lot of data like Post and function like sqlToVal. Can I reduce this boilerplate code for sqlToVal?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-04T09:48:22+00:00Added an answer on June 4, 2026 at 9:48 am

    Template Haskell code generation is a very advanced topic. Still, if you master the art of TH it is possible to use said technique to generate the code that you’re looking for.

    Note that the following code will only work for data types with only one constructor (E.g. not data Foo = A String Int | B String Int, which has two constructors A and B) because you didn’t say how that should be handled in the code.

    We will make a Template Haskell function that runs at compile time, takes the name of a data type, and generates a function called sqlTo<nameofdatatype>. This function looks like this:

    module THTest where
    
    import Control.Monad (replicateM)
    
    -- Import Template Haskell
    import Language.Haskell.TH
    -- ...and a representation of Haskell syntax
    import Language.Haskell.TH.Syntax
    
    -- A function that takes the name of a data type and generates a list of
    -- (function) declarations (of length 1).
    makeSqlDeserializer :: Name -> Q [Dec]
    makeSqlDeserializer name = do
      -- Look up some information about the name. This gets information about what
      -- the name represents.
      info <- reify name
    
      case info of
        -- Is the name a type constructor (TyConI) of a data type (DataD), with
        -- only one normal constructor (NormalC)? Then, carry on.
        -- dataName is the name of the type, constrName of the constructor, and
        -- the paramTypes are the constructor parameter types.
        -- So, if we have `data A = B String Int`, we get
        -- dataName = A, constrName = B, paramTypes = [String, Int]
        TyConI (DataD _ dataName _ [NormalC constrName paramTypes] _) -> do
    
          -- If the dataName has a module name (Foo.Bar.Bla), only return the data
          -- name (Bla)
          let dataBaseName = nameBase dataName
    
          -- Make a function name like "sqlToBla"
          let funcName = mkName $ "sqlTo" ++ dataBaseName
    
          -- Also access the "fromSql" function which we need below.
          let fromSqlName = mkName "Database.HDBC.fromSql"
    
          -- Count how many params our data constructor takes.
          let numParams = length paramTypes
    
          -- Create numParams new names, which are variable names with random
          -- names.
          -- This could create names like [param1, param2, param3] for example,
          -- but typically they will look like
          -- [param[aV2], param[aV3], param[aV4]]
          paramNames <- replicateM numParams $ newName "param"
    
          -- The patterns are what's on the left of the `=` in the function, e.g.
          -- sqlToBla >>>[param1, param2, param3]<<< = ...
          -- We make a list pattern here which matches a list of length numParams
          let patterns = [ListP $ map VarP paramNames]
    
          -- The constructor params are the params that are sent to the
          -- constructor:
          -- ... = Bla >>>(fromSql param1) (fromSql param2) (fromSql param3)<<<
          let constrParams = map (AppE (VarE fromSqlName) . VarE) paramNames
    
          -- Make a body where we simply apply the constructor to the params
          -- ... = >>>Bla (fromSql param1) (fromSql param2) (fromSql param3)<<<
          let body = NormalB (foldl AppE (ConE constrName) constrParams)
    
          -- Return a new function declaration that does what we want.
          -- It has only one clause with the patterns that are specified above.
          -- sqlToBla [param1, param2, param3] =
          --   Bla (fromSql param1) (fromSql param2) (fromSql param3)
          return [FunD funcName [Clause patterns body []]]
    

    Now, we use this function like so (Note the LANGUAGE pragma which enables Template Haskell):

    {-# LANGUAGE TemplateHaskell #-}
    
    -- The module that defines makeSqlDeserializer (must be in a different module!)
    import THTest
    
    -- Also import the fromSql function which is needed by the generated function.
    import Database.HDBC
    
    -- Declare the data type
    data Bla = Bla String Int deriving (Show)
    
    -- Generate the sqlToBla function
    makeSqlDeserializer ''Bla
    

    If you want to see the function that is generated, simply pass -ddump-splices to GHC when compiling. The output is something like this:

    test.hs:1:1: Splicing declarations
        makeSqlDeserializer 'Bla
      ======>
        test.hs:7:1-25
        sqlToBla [param[aV2], param[aV3]]
          = Bla (Database.HDBC.fromSql param[aV2]) (Database.HDBC.fromSql param[aV3])
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

In my project I have a lot of code like this: int[][] a =
I have a lot of C# VS2008 code that looks like this: new SqlParameter(@Description,
I have tried a lot on this code but it keeps messing up. The
In my code right now I have something like this: state.BytesRead += readPacket.Result; if
I am have a lot of code that I need to optimize and make
DirectDraw 7 is very old APIs but we have a lot legacy code written
I have a lot of pieces of code which has to be run one
Currently I have a lot of python objects in my code similar to the
On my blog I have a lot of <pre> blocks containing code snippets. What
Ok, We have a lot of where clauses in our code. We have just

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.