{-# LANGUAGE AllowAmbiguousTypes #-} -- due to type class design
module Generic.Data.Function.Contra
( GenericContra(..)
, genericContraNonSum, GContraNonSum
, genericContraSum, GContraSum
) where
import GHC.Generics
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 {k} (tag :: k) a
. ( Generic a
, Contravariant (GenericContraF tag)
, GContraNonSum tag (Rep a)
) => GenericContraF tag a
genericContraNonSum = contramap 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 {k} (tag :: k) opts a
. ( Generic a
, Contravariant (GenericContraF tag)
, GContraSum tag opts (Rep a)
) => GenericContraF tag String -> GenericContraF tag a
genericContraSum f = contramap from (gContraSum @tag @opts f)