Alternatively, if you don’t mind generating code that is not optimized for human readability, you could pre-desugar the do-notation and records like this:
spliceStmts [] k = k
spliceStmts (x:xs) k = [| $x >> $(spliceStmts xs k) |]
spliceRevApp f [] = f
spliceRevApp f (x:xs) = [| $(spliceApp f xs) $x |]
...
[d|
$(varE 'sqlSelectProcessRow) cols =
first ((fromString "Failed to parse " ++ $(lift (nameBase name)) ++ ": ") <>)
flip evalStateT cols $
$(spliceStmts statements (spliceRevApp (varE name) (reverse fieldExps)))
|]
Of course there are still some problems that need to be ironed out, like that spliceStmts
only supports statements that do not bind variables.