{-# LANGUAGE AllowAmbiguousTypes #-} -- due to type class design
module Generic.Data.Function.Contra
( GenericContra(..)
, genericContraNonSum, GContraNonSum
, genericContraSum, GContraSum
) where
import GHC.Generics
import Generic.Data.Rep.Assert
import Generic.Data.Function.Contra.NonSum
import Generic.Data.Function.Contra.Sum
import Generic.Data.Function.Contra.Constructor
import Data.Functor.Contravariant
-- | Generic contra over a term of non-sum data type @a@.
--
-- @a@ must have exactly one constructor.
genericContraNonSum
:: forall {cd} {gf} asserts tag a
. ( Generic a, Rep a ~ D1 cd gf
, GContraNonSum tag gf
, ApplyGCAsserts asserts gf
, Contravariant (GenericContraF tag))
=> GenericContraF tag a
genericContraNonSum = contramap (unM1 . from) (gContraNonSum @tag)
-- | Generic contra over a term of sum data type @a@.
--
-- You must provide a contra function for constructor names.
--
-- This is the most generic option, but depending on your string manipulation
-- may be slower.
genericContraSum
:: forall {cd} {gf} opts asserts tag a
. ( Generic a, Rep a ~ D1 cd gf
, GContraSum opts tag gf
, ApplyGCAsserts asserts gf
, Contravariant (GenericContraF tag))
=> GenericContraF tag String
-> GenericContraF tag a
genericContraSum f = contramap (unM1 . from) (gContraSum @opts @tag f)