我以下列方式调用我的TH函数,称为createRecordSplice
:
data User = User {userFoo :: String, userBar :: Text} deriving (Eq, Show, Generic)
createRecordSplice "user" ''User ['userBar] "NewUser" "nuser"
请注意,记录选择器userBar
使用单引号传递。
现在,在我的TH函数中,我要检查User
对userBar
的字段名称,我遇到了一个包含$sel
的奇怪字段名称,由于其中,我的主要逻辑是无法工作。
(Common.TestRecordSplices.userFoo,[Common.TestRecordSplices.$sel:userBar:User])
(Common.TestRecordSplices.userBar,[Common.TestRecordSplices.$sel:userBar:User])
这是$sel:userBar:User
是什么?如果不诉诸字符串操作,如何将userBar
转换为$sel:userBar:User
,反之亦然?
我的TH功能:
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))