## aeson-generic-default Type-level configuration of missing values for aeson FromJSON Generic parser. Using higher-kinded-types, Coercible and Generic instances it is possible to define a class that can be configured by a type parameter to use custom field parsers during parsing and only when the parsing is done, it can be coerced to use normal types. ```haskell data ConfigFileT d = ConfigFile { defaultEnabled :: DefaultField d (DefBool True) , defaultDisabled :: DefaultField d (DefBool False) , defaultText :: DefaultField d (DefText "default text") , defaultInt :: DefaultField d (DefInt 42) , defaultNegativeInt :: DefaultField d (DefNegativeInt 42) , defaultRed :: DefaultField d (DefDefault Color) , defaultBlue :: DefaultField d (DefDefaultConstant BlueDefault) , normalField :: T.Text , normalOptional :: Maybe Int } deriving (Generic) type ConfigFile = ConfigFileT Final instance FromJSON ConfigFile where parseJSON = parseWithDefaults defaultOptions ``` The resulting `ConfigFile` type alias has a form of: ```haskell { defaultEnabled :: Bool , defaultDisabled :: Bool , defaultText :: Text , defaultInt :: Int , defaultNegativeInt :: Int , defaultRed :: Color , defaultBlue :: Color , normalField :: T.Text , normalOptional :: Maybe Int } ``` The type-level configuration can be easily extended with newtypes, e.g. to create a full compatibility layer with `singletons`: ```haskell newtype DefSing (a :: k) = DefSing (Demote k) deriving Generic instance (SingI a, SingKind k, FromJSON (Demote k)) => FromJSON (DefSing (a :: k)) where omittedField = Just $ DefSing $ fromSing (sing @a) parseJSON v = DefSing <$> parseJSON v ``` And then the definition of the field can be for any singleton (e.g. Bool): ```haskell flag :: DefaultField d (DefSing True) ```