module Database.Sybase.Sysmon.Derive where
import Database.Sybase.Sysmon.Average
import Language.Haskell.TH
import Control.Monad
genpe :: String -> Int -> Q ([PatQ],[ExpQ])
genpe s n = do
ns <- replicateM n (newName s)
return (map varP ns, map varE ns)
deriveAverage t = do
TyConI (DataD _ _ _ constructors _) <- reify t
let avgClause (RecC name fields) = do
([xsp], [xsv]) <- genpe "xs" 1
(pats, vars) <- genpe "x" (length fields)
let mkApp [x,y] = appE x y
mkApp (x:ys) = appE (mkApp (init (x:ys))) (last ys)
let vare s = varE (mkName s)
let dec (vp, fld) = valD
vp
(normalB
(appE
(vare "avg")
(appE
(appE (vare "map") (varE fld))
xsv)
)
) []
let declst (vp, fld) = valD
vp
(normalB
(appE
(appE (vare "map") (vare "avg"))
(appE (vare "transpose")
(appE
(appE (vare "map") (varE fld))
xsv)))) []
let decl (vp, (fld, _, typ)) = case typ of
AppT _ _ -> declst (vp, fld)
_ -> dec (vp, fld)
let decls = map decl $ zip pats fields
clause [xsp] (normalB $ mkApp (conE name : vars)) decls
body <- mapM avgClause constructors
return [InstanceD [] (AppT (ConT $ mkName "Averageable") (ConT t))
[FunD (mkName "avg") body]
]