doCons :: Con -> (ClauseQ, ClauseQ)
doCons (NormalC c vs@((_,VarT n):sts)) =
  let annDef = clause [conP c (varP n : map (const wildP) sts)] (normalB (varE n)) []

      nams = [ mkName x | x <- zipWith (\_ i -> "x" ++ show i) vs ([0..]::[Int]) ]
      f    = mkName "f"
      arg1 = [| $(varE f) $(varE (head nams)) |]
      args = [ varE nam | nam <- tail nams ]
      rhs  = foldl appE (conE c) (arg1:args)
      amapDef = clause [varP f, conP c (map varP nams)] (normalB rhs) []
  in (annDef, amapDef)
doCons :: Con -> (ClauseQ, ClauseQ)
doCons (NormalC c vs@((_,VarT n):sts)) =
  let annDef = clause [conP c (varP n : map (const wildP) sts)] (normalB (varE n)) []

      nams = [ mkName x | x <- zipWith (\_ i -> "x" ++ show i) vs ([0..]::[Int]) ]
      f    = mkName "f"
      arg1 = [| $(varE f) $(varE (head nams)) |]
      args = [ varE nam | nam <- tail nams ]
      rhs  = foldl appE (conE c) (arg1:args)
      amapDef = clause [varP f, conP c (map varP nams)] (normalB rhs) []
  in (annDef, amapDef)
doCons (NormalC c vs@((_,VarT n):sts)) =
  let annDef = clause [conP c (varP n : map (const wildP) sts)] (normalB (varE n)) []

      nams = [ mkName x | x <- zipWith (\_ i -> "x" ++ show i) vs ([0..]::[Int]) ]
      f    = mkName "f"
      arg1 = [| $(varE f) $(varE (head nams)) |]
      args = [ varE nam | nam <- tail nams ]
      rhs  = foldl appE (conE c) (arg1:args)
      amapDef = clause [varP f, conP c (map varP nams)] (normalB rhs) []
  in (annDef, amapDef)