@@ -362,34 +362,43 @@ deriveSerializeInternal preds headTy cons = do
362362 ]
363363 return [plainInstanceD preds (AppT (ConT ''Serialize) headTy) methods]
364364
365−-- | Template haskell helper to create instances of 'Serialize' automatically.
365+-- | Similar to 'deriveSerialize,' but with the ability to specify which type
366+-- variables should not be subjected to the 'Serialize' constraint and how to
367+-- replace these variables when defining the 'Serialize' instance for the
368+-- primary data type.
366369--
367370-- Consider the datatype:
368371-- @
369−-- data CustomDataType a b c = ...
372+-- data CustomDataType a f c = CDT a (f Int)
370373-- @
371374--
372−-- Usage: @$(deriveSerialize ''CustomDataType)@
375+-- Usage: @$(deriveSerializeWith ["c", "f"] [("f", ConT ''Identity)] ''CustomDataType)@
373376--
374−-- Note: All type variables automatcally get an "Serialize" constraint.
375−-- The derived code will look like the following,
376377-- @
377−-- instance (Serialize a, Serialize b, Serialize c) => Serialize (CustomDataType a b c) where
378+-- instance (Serialize a) => Serialize (CustomDataType a Identity c) where
378379-- ...
379380-- @
380381--
381−-- To control which type variables get the Serialize constraint, use
382−-- 'deriveSerializeWith'.
383−deriveSerialize :: Name -> Q [Dec]
384−deriveSerialize name = do
382+-- In the above example, 'Serialize' constraint is omitted for @f@ and @c@, and
383+-- @f@ is replaced with 'Identity' when defining the 'Serialize' instance for
384+-- the primary data type.
385+deriveSerializeWith :: [String] -> [(String, Type)] -> Name -> Q [Dec]
386+deriveSerializeWith ignoring substitutions name = do
385387 dt <- reifyDataType name
386− let preds = map (unboxPred . VarT) (dtTvs dt)
387− headTy = appsT (ConT name) (map VarT (dtTvs dt))
388+ let preds = map (unboxPred . VarT) (filterOutVars (dtTvs dt))
389+ headTy = appsT (ConT name) (map substituteVar (dtTvs dt))
388390 cons = dtCons dt
389391 deriveSerializeInternal preds headTy cons
390392
391393 where
392394
395+ filterOutVars vs =
396+ map mkName $ filter (not . flip elem ignoring) $ map nameBase vs
397+ substituteVar v =
398+ case lookup (nameBase v) substitutions of
399+ Nothing -> VarT v
400+ Just ty -> ty
401+
393402 unboxPred ty =
394403#if MIN_VERSION_template_haskell(2,10,0)
395404 AppT (ConT ''Serialize) ty
@@ -397,34 +406,25 @@ deriveSerialize name = do
397406 ClassP ''Serialize [ty]
398407#endif
399408
400−-- | Like 'deriveSerialize' but control which types variables get the 'Serialize'
401−-- constraint.
409+-- | Template haskell helper to create instances of 'Serialize' automatically.
402410--
403411-- Consider the datatype:
404412-- @
405413-- data CustomDataType a b c = ...
406414-- @
407415--
408−-- Usage: @$(deriveSerializeWith ["a", "c"] ''CustomDataType)@
416+-- Usage: @$(deriveSerialize ''CustomDataType)@
409417--
418+-- Note: All type variables automatcally get an "Serialize" constraint.
419+-- The derived code will look like the following,
410420-- @
411−-- instance (Serialize a, Serialize c) => Serialize (CustomDataType a b c) where
421+-- instance (Serialize a, Serialize b, Serialize c) => Serialize (CustomDataType a b c) where
412422-- ...
413423-- @
414424--
415−deriveSerializeWith :: [String] -> Name -> Q [Dec]
416−deriveSerializeWith vars name = do
417− dt <- reifyDataType name
418− let preds = map (unboxPred . VarT) (fmap mkName vars)
419− headTy = appsT (ConT name) (map VarT (dtTvs dt))
420− cons = dtCons dt
421− deriveSerializeInternal preds headTy cons
422−
423− where
424−
425− unboxPred ty =
426−#if MIN_VERSION_template_haskell(2,10,0)
427− AppT (ConT ''Serialize) ty
428−#else
429− ClassP ''Serialize [ty]
430−#endif
425+-- To control which type variables don't get the Serialize constraint, use
426+-- 'deriveSerializeWith'.
427+--
428+-- >>> deriveSerialize = deriveSerializeWith [] []
429+deriveSerialize :: Name -> Q [Dec]
430+deriveSerialize name = deriveSerializeWith [] [] name