packages feed

generic-data-functions-0.3.0: src/Generic/Data/Function/Contra.hs

{-# 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)