@@ -272,7 +272,7 @@ module Extensible
272272 -- ** Template Haskell re-exports
273273 newName , varT ,
274274 -- * Generating extensible datatypes
275- extensible , extensibleWith , Config (.. ), defaultConfig )
275+ extensible , extensibleWith , Config (.. ), defaultConfig , WarningType ( .. ) )
276276where
277277
278278import Language.Haskell.TH as TH
@@ -337,8 +337,10 @@ qualifyWith m n = case nameModule n of
337337 Just _ -> n
338338
339339
340- -- | Configuration options for how to name the generated constructors, type
341- -- families, etc.
340+ data WarningType = Ignore | Warn | Error deriving (Eq , Show , Lift )
341+
342+ -- | Configuration options for warning behaviour, as well as how to name the
343+ -- generated constructors, type families, etc.
342344data Config = Config {
343345 -- | Applied to input datatype's name to get extensible type's name
344346 datatypeName :: NameAffix ,
@@ -366,7 +368,10 @@ data Config = Config {
366368 defExtRecName :: NameAffix ,
367369 -- | Applied to datatype name to get the name of the extension
368370 -- generator function
369- extFunName :: NameAffix
371+ extFunName :: NameAffix ,
372+ -- | What to do when encountering a newtype. For @Warn@ and @Ignore@, it is
373+ -- treated as a strict datatype.
374+ newtypeWarn :: WarningType
370375 } deriving (Eq , Show , Lift )
371376
372377-- | Default config:
@@ -375,15 +380,16 @@ data Config = Config {
375380-- Config {
376381-- datatypeName = NameSuffix \"'\",
377382-- constructorName = NameSuffix \"'\",
378- -- bundleName = NameSuffix "All",
383+ -- bundleName = NameSuffix \ "All\ ",
379384-- annotationName = NamePrefix \"X\",
380385-- extensionName = NameSuffix \"X\",
381386-- extensionLabel = NamePrefix \"ext\",
382387-- extRecordName = NamePrefix \"Ext\",
383388-- extRecTypeName = NamePrefix \"type\",
384389-- extRecNameName = NamePrefix \"name\",
385390-- defExtRecName = NamePrefix \"default\",
386- -- extFunName = NamePrefix \"extend\"
391+ -- extFunName = NamePrefix \"extend\",
392+ -- newtypeWarn = Warn
387393-- }
388394-- @
389395defaultConfig :: Config
@@ -398,7 +404,8 @@ defaultConfig = Config {
398404 extRecTypeName = NamePrefix " type" ,
399405 extRecNameName = NamePrefix " name" ,
400406 defExtRecName = NamePrefix " default" ,
401- extFunName = NamePrefix " extend"
407+ extFunName = NamePrefix " extend" ,
408+ newtypeWarn = Warn
402409 }
403410
404411
@@ -433,15 +440,32 @@ data SimpleDeriv =
433440
434441-- | Extract a 'SimpleData' from a 'Dec', if it is a datatype with the given
435442-- restrictions.
436- simpleData :: Dec -> Q SimpleData
437- simpleData (DataD ctx name tvs kind cons derivs)
443+ simpleData :: WarningType -> Dec -> Q SimpleData
444+ simpleData _w (DataD ctx name tvs kind cons derivs)
438445 | not $ null ctx = fail " data contexts unsupported"
439446 | Just _ <- kind = fail " kind signatures unsupported"
440447 | otherwise =
441448 SimpleData name tvs
442449 <$> traverse simpleCon cons
443450 <*> traverse simpleDeriv derivs
444- simpleData _ = fail " not a datatype"
451+ simpleData Error (NewtypeD _ name _ _ _ _) =
452+ fail $
453+ " newtype " ++ nameBase name ++ " found\n " ++
454+ " please replace it with a datatype"
455+ simpleData Warn n@ (NewtypeD _ name _ _ _ _) = do
456+ reportWarning $
457+ " replacing newtype " ++ nameBase name ++ " with data\n " ++
458+ " (due to adding another field and a second constructor)\n " ++
459+ " you may want to replace the newtype with a (strict) datatype"
460+ simpleData Ignore n
461+ simpleData Ignore (NewtypeD ctx name tvs kind con derivs) =
462+ simpleData Ignore $ DataD ctx name tvs kind [makeStrict con] derivs
463+ where
464+ makeStrict = everywhere $ mkT $ const $ Bang NoSourceUnpackedness SourceStrict
465+ simpleData _w d =
466+ fail $
467+ " only datatype declarations are supported inside extensible; found\n " ++
468+ pprint d
445469
446470-- | Extract a 'SimpleCon' from a 'Con', if it is the 'NormalC' case.
447471simpleCon :: Con -> Q SimpleCon
@@ -468,7 +492,7 @@ extensible = extensibleWith defaultConfig
468492-- function spits out.
469493extensibleWith :: Config -> DecsQ -> DecsQ
470494extensibleWith conf ds = do
471- ds' <- traverse simpleData =<< ds
495+ ds' <- traverse ( simpleData (newtypeWarn conf)) =<< ds
472496 home <- loc_module <$> location
473497 makeExtensible conf home ds'
474498
0 commit comments