module Air.Data.Record.SimpleLabel.TH (mkLabels, mkLabel) where import Control.Monad import Data.Char import Language.Haskell.TH.Syntax -- | Derive labels for all the record selector in a datatype. mkLabels :: [Name] -> Q [Dec] mkLabels = liftM concat . mapM mkLabel mkLabel :: Name -> Q [Dec] mkLabel n = do i <- reify n let -- only process data and newtype declarations cs' = case i of TyConI (DataD _ _ _ cs _) -> cs TyConI (NewtypeD _ _ _ c _) -> [c] _ -> [] -- we're only interested in labels of record constructors ls' = [ l | RecC _ ls <- cs', l <- ls ] return (map mkLabel1 ls') mkLabel1 :: VarStrictType -> Dec mkLabel1 (name, _, _) = -- Generate a name for the label: -- in this fork: label names are "__" + accesser name, e.g. if data Square = Square {length :: Double}, then label is __length let n = mkName $ "__" ++ nameBase name in FunD n [Clause [] (NormalB ( AppE (AppE (VarE (mkName "label")) (VarE name)) -- getter (LamE [VarP (mkName "b"), VarP (mkName "a")] -- setter (RecUpdE (VarE (mkName "a")) [(name, VarE (mkName "b"))])) )) []]