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?
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
datatypes with only one constructor (E.g. notdata Foo = A String Int | B String Int, which has two constructorsAandB) 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:Now, we use this function like so (Note the
LANGUAGEpragma which enables Template Haskell):If you want to see the function that is generated, simply pass
-ddump-splicesto GHC when compiling. The output is something like this: