I'm calling my TH function, called createRecordSplice
in the following manner:
data User = User {userFoo :: String, userBar :: Text} deriving (Eq, Show, Generic)
createRecordSplice "user" ''User ['userBar] "NewUser" "nuser"
Notice that the record selector userBar
is passed with a single-quote.
Now, in my TH function where I want to check the field names of User
against userBar
, I'm encountering a strange field name which contains $sel
, due to which, my main logic is failing to work.
(Common.TestRecordSplices.userFoo,[Common.TestRecordSplices.$sel:userBar:User])
(Common.TestRecordSplices.userBar,[Common.TestRecordSplices.$sel:userBar:User])
What is this $sel:userBar:User
and how does one convert userBar
to $sel:userBar:User
, or vice versa, without resorting to string manipulation?
My TH function:
createRecordSplice :: String -> Name -> [Name] -> String -> String -> Q [Dec]
createRecordSplice sourcePrefix record requiredFields newRectype targetPrefix = reify record >>= \case
(TyConI (DataD [] recordConstr [] knd constrs classes)) -> case constrs of
[(RecC _ sourceFields)] -> do
let newFields = DL.foldl'
(\memo (fname, bang, ftype) ->
-- OUTPUT FOR THIS TRACE IS GIVEN ABOVE
trace (show (nameBase fname, nameBase <$> requiredFields)) $
if (fname `elem` requiredFields)
then (sourceToTargetName fname, bang, ftype):memo
else memo
) [] sourceFields
runIO $ putStrLn (show newFields)
pure $ [DataD [] (mkName newRectype) [] knd [RecC (mkName newRectype) newFields] classes]
_ -> fail $ "creating record splices for types with multiple constructors (sum types), i.e. data X = Y | Z, is not supported yet"
where
sourceToTargetName n = mkName $ targetPrefix ++ (DL.drop (DL.length sourcePrefix) (nameBase n))